6274 lines
294 KiB
TypeScript
6274 lines
294 KiB
TypeScript
namespace ts {
|
|
let nextAutoGenerateId = 0;
|
|
|
|
/* @internal */
|
|
export const enum NodeFactoryFlags {
|
|
None = 0,
|
|
// Disables the parenthesizer rules for the factory.
|
|
NoParenthesizerRules = 1 << 0,
|
|
// Disables the node converters for the factory.
|
|
NoNodeConverters = 1 << 1,
|
|
// Ensures new `PropertyAccessExpression` nodes are created with the `NoIndentation` emit flag set.
|
|
NoIndentationOnFreshPropertyAccess = 1 << 2,
|
|
// Do not set an `original` pointer when updating a node.
|
|
NoOriginalNode = 1 << 3,
|
|
}
|
|
|
|
/**
|
|
* Creates a `NodeFactory` that can be used to create and update a syntax tree.
|
|
* @param flags Flags that control factory behavior.
|
|
* @param baseFactory A `BaseNodeFactory` used to create the base `Node` objects.
|
|
*/
|
|
/* @internal */
|
|
export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNodeFactory): NodeFactory {
|
|
const update = flags & NodeFactoryFlags.NoOriginalNode ? updateWithoutOriginal : updateWithOriginal;
|
|
|
|
// Lazily load the parenthesizer, node converters, and some factory methods until they are used.
|
|
const parenthesizerRules = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory));
|
|
const converters = memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory));
|
|
|
|
// lazy initializaton of common operator factories
|
|
const getBinaryCreateFunction = memoizeOne((operator: BinaryOperator) => (left: Expression, right: Expression) => createBinaryExpression(left, operator, right));
|
|
const getPrefixUnaryCreateFunction = memoizeOne((operator: PrefixUnaryOperator) => (operand: Expression) => createPrefixUnaryExpression(operator, operand));
|
|
const getPostfixUnaryCreateFunction = memoizeOne((operator: PostfixUnaryOperator) => (operand: Expression) => createPostfixUnaryExpression(operand, operator));
|
|
const getJSDocPrimaryTypeCreateFunction = memoizeOne(<T extends JSDocType>(kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind));
|
|
const getJSDocUnaryTypeCreateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"]) => (type: T["type"]) => createJSDocUnaryTypeWorker<T>(kind, type));
|
|
const getJSDocUnaryTypeUpdateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocUnaryTypeWorker<T>(kind, node, type));
|
|
const getJSDocSimpleTagCreateFunction = memoizeOne(<T extends JSDocTag>(kind: T["kind"]) => (tagName: Identifier | undefined, comment?: string) => createJSDocSimpleTagWorker(kind, tagName, comment));
|
|
const getJSDocSimpleTagUpdateFunction = memoizeOne(<T extends JSDocTag>(kind: T["kind"]) => (node: T, tagName: Identifier | undefined, comment?: string) => updateJSDocSimpleTagWorker(kind, node, tagName, comment));
|
|
const getJSDocTypeLikeTagCreateFunction = memoizeOne(<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"]) => (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string) => createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment));
|
|
const getJSDocTypeLikeTagUpdateFunction = memoizeOne(<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"]) => (node: T, tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string) => updateJSDocTypeLikeTagWorker(kind, node, tagName, typeExpression, comment));
|
|
|
|
const factory: NodeFactory = {
|
|
get parenthesizer() { return parenthesizerRules(); },
|
|
get converters() { return converters(); },
|
|
createNodeArray,
|
|
createNumericLiteral,
|
|
createBigIntLiteral,
|
|
createStringLiteral,
|
|
createStringLiteralFromNode,
|
|
createRegularExpressionLiteral,
|
|
createLiteralLikeNode,
|
|
createIdentifier,
|
|
updateIdentifier,
|
|
createTempVariable,
|
|
createLoopVariable,
|
|
createUniqueName,
|
|
getGeneratedNameForNode,
|
|
createPrivateIdentifier,
|
|
createToken,
|
|
createSuper,
|
|
createThis,
|
|
createNull,
|
|
createTrue,
|
|
createFalse,
|
|
createModifier,
|
|
createModifiersFromModifierFlags,
|
|
createQualifiedName,
|
|
updateQualifiedName,
|
|
createComputedPropertyName,
|
|
updateComputedPropertyName,
|
|
createTypeParameterDeclaration,
|
|
updateTypeParameterDeclaration,
|
|
createParameterDeclaration,
|
|
updateParameterDeclaration,
|
|
createDecorator,
|
|
updateDecorator,
|
|
createPropertySignature,
|
|
updatePropertySignature,
|
|
createPropertyDeclaration,
|
|
updatePropertyDeclaration,
|
|
createMethodSignature,
|
|
updateMethodSignature,
|
|
createMethodDeclaration,
|
|
updateMethodDeclaration,
|
|
createConstructorDeclaration,
|
|
updateConstructorDeclaration,
|
|
createGetAccessorDeclaration,
|
|
updateGetAccessorDeclaration,
|
|
createSetAccessorDeclaration,
|
|
updateSetAccessorDeclaration,
|
|
createCallSignature,
|
|
updateCallSignature,
|
|
createConstructSignature,
|
|
updateConstructSignature,
|
|
createIndexSignature,
|
|
updateIndexSignature,
|
|
createKeywordTypeNode,
|
|
createTypePredicateNode,
|
|
updateTypePredicateNode,
|
|
createTypeReferenceNode,
|
|
updateTypeReferenceNode,
|
|
createFunctionTypeNode,
|
|
updateFunctionTypeNode,
|
|
createConstructorTypeNode,
|
|
updateConstructorTypeNode,
|
|
createTypeQueryNode,
|
|
updateTypeQueryNode,
|
|
createTypeLiteralNode,
|
|
updateTypeLiteralNode,
|
|
createArrayTypeNode,
|
|
updateArrayTypeNode,
|
|
createTupleTypeNode,
|
|
updateTupleTypeNode,
|
|
createNamedTupleMember,
|
|
updateNamedTupleMember,
|
|
createOptionalTypeNode,
|
|
updateOptionalTypeNode,
|
|
createRestTypeNode,
|
|
updateRestTypeNode,
|
|
createUnionTypeNode,
|
|
updateUnionTypeNode,
|
|
createIntersectionTypeNode,
|
|
updateIntersectionTypeNode,
|
|
createConditionalTypeNode,
|
|
updateConditionalTypeNode,
|
|
createInferTypeNode,
|
|
updateInferTypeNode,
|
|
createImportTypeNode,
|
|
updateImportTypeNode,
|
|
createParenthesizedType,
|
|
updateParenthesizedType,
|
|
createThisTypeNode,
|
|
createTypeOperatorNode,
|
|
updateTypeOperatorNode,
|
|
createIndexedAccessTypeNode,
|
|
updateIndexedAccessTypeNode,
|
|
createMappedTypeNode,
|
|
updateMappedTypeNode,
|
|
createLiteralTypeNode,
|
|
updateLiteralTypeNode,
|
|
createObjectBindingPattern,
|
|
updateObjectBindingPattern,
|
|
createArrayBindingPattern,
|
|
updateArrayBindingPattern,
|
|
createBindingElement,
|
|
updateBindingElement,
|
|
createArrayLiteralExpression,
|
|
updateArrayLiteralExpression,
|
|
createObjectLiteralExpression,
|
|
updateObjectLiteralExpression,
|
|
createPropertyAccessExpression: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ?
|
|
(expression, name) => setEmitFlags(createPropertyAccessExpression(expression, name), EmitFlags.NoIndentation) :
|
|
createPropertyAccessExpression,
|
|
updatePropertyAccessExpression,
|
|
createPropertyAccessChain: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ?
|
|
(expression, questionDotToken, name) => setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), EmitFlags.NoIndentation) :
|
|
createPropertyAccessChain,
|
|
updatePropertyAccessChain,
|
|
createElementAccessExpression,
|
|
updateElementAccessExpression,
|
|
createElementAccessChain,
|
|
updateElementAccessChain,
|
|
createCallExpression,
|
|
updateCallExpression,
|
|
createCallChain,
|
|
updateCallChain,
|
|
createNewExpression,
|
|
updateNewExpression,
|
|
createTaggedTemplateExpression,
|
|
updateTaggedTemplateExpression,
|
|
createTypeAssertion,
|
|
updateTypeAssertion,
|
|
createParenthesizedExpression,
|
|
updateParenthesizedExpression,
|
|
createFunctionExpression,
|
|
updateFunctionExpression,
|
|
createArrowFunction,
|
|
updateArrowFunction,
|
|
createDeleteExpression,
|
|
updateDeleteExpression,
|
|
createTypeOfExpression,
|
|
updateTypeOfExpression,
|
|
createVoidExpression,
|
|
updateVoidExpression,
|
|
createAwaitExpression,
|
|
updateAwaitExpression,
|
|
createPrefixUnaryExpression,
|
|
updatePrefixUnaryExpression,
|
|
createPostfixUnaryExpression,
|
|
updatePostfixUnaryExpression,
|
|
createBinaryExpression,
|
|
updateBinaryExpression,
|
|
createConditionalExpression,
|
|
updateConditionalExpression,
|
|
createTemplateExpression,
|
|
updateTemplateExpression,
|
|
createTemplateHead,
|
|
createTemplateMiddle,
|
|
createTemplateTail,
|
|
createNoSubstitutionTemplateLiteral,
|
|
createTemplateLiteralLikeNode,
|
|
createYieldExpression,
|
|
updateYieldExpression,
|
|
createSpreadElement,
|
|
updateSpreadElement,
|
|
createClassExpression,
|
|
updateClassExpression,
|
|
createOmittedExpression,
|
|
createExpressionWithTypeArguments,
|
|
updateExpressionWithTypeArguments,
|
|
createAsExpression,
|
|
updateAsExpression,
|
|
createNonNullExpression,
|
|
updateNonNullExpression,
|
|
createNonNullChain,
|
|
updateNonNullChain,
|
|
createMetaProperty,
|
|
updateMetaProperty,
|
|
createTemplateSpan,
|
|
updateTemplateSpan,
|
|
createSemicolonClassElement,
|
|
createBlock,
|
|
updateBlock,
|
|
createVariableStatement,
|
|
updateVariableStatement,
|
|
createEmptyStatement,
|
|
createExpressionStatement,
|
|
updateExpressionStatement,
|
|
createIfStatement,
|
|
updateIfStatement,
|
|
createDoStatement,
|
|
updateDoStatement,
|
|
createWhileStatement,
|
|
updateWhileStatement,
|
|
createForStatement,
|
|
updateForStatement,
|
|
createForInStatement,
|
|
updateForInStatement,
|
|
createForOfStatement,
|
|
updateForOfStatement,
|
|
createContinueStatement,
|
|
updateContinueStatement,
|
|
createBreakStatement,
|
|
updateBreakStatement,
|
|
createReturnStatement,
|
|
updateReturnStatement,
|
|
createWithStatement,
|
|
updateWithStatement,
|
|
createSwitchStatement,
|
|
updateSwitchStatement,
|
|
createLabeledStatement,
|
|
updateLabeledStatement,
|
|
createThrowStatement,
|
|
updateThrowStatement,
|
|
createTryStatement,
|
|
updateTryStatement,
|
|
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,
|
|
createNamespaceExport,
|
|
updateNamespaceExport,
|
|
createNamedImports,
|
|
updateNamedImports,
|
|
createImportSpecifier,
|
|
updateImportSpecifier,
|
|
createExportAssignment,
|
|
updateExportAssignment,
|
|
createExportDeclaration,
|
|
updateExportDeclaration,
|
|
createNamedExports,
|
|
updateNamedExports,
|
|
createExportSpecifier,
|
|
updateExportSpecifier,
|
|
createMissingDeclaration,
|
|
createExternalModuleReference,
|
|
updateExternalModuleReference,
|
|
// lazily load factory members for JSDoc types with similar structure
|
|
get createJSDocAllType() { return getJSDocPrimaryTypeCreateFunction<JSDocAllType>(SyntaxKind.JSDocAllType); },
|
|
get createJSDocUnknownType() { return getJSDocPrimaryTypeCreateFunction<JSDocUnknownType>(SyntaxKind.JSDocUnknownType); },
|
|
get createJSDocNonNullableType() { return getJSDocUnaryTypeCreateFunction<JSDocNonNullableType>(SyntaxKind.JSDocNonNullableType); },
|
|
get updateJSDocNonNullableType() { return getJSDocUnaryTypeUpdateFunction<JSDocNonNullableType>(SyntaxKind.JSDocNonNullableType); },
|
|
get createJSDocNullableType() { return getJSDocUnaryTypeCreateFunction<JSDocNullableType>(SyntaxKind.JSDocNullableType); },
|
|
get updateJSDocNullableType() { return getJSDocUnaryTypeUpdateFunction<JSDocNullableType>(SyntaxKind.JSDocNullableType); },
|
|
get createJSDocOptionalType() { return getJSDocUnaryTypeCreateFunction<JSDocOptionalType>(SyntaxKind.JSDocOptionalType); },
|
|
get updateJSDocOptionalType() { return getJSDocUnaryTypeUpdateFunction<JSDocOptionalType>(SyntaxKind.JSDocOptionalType); },
|
|
get createJSDocVariadicType() { return getJSDocUnaryTypeCreateFunction<JSDocVariadicType>(SyntaxKind.JSDocVariadicType); },
|
|
get updateJSDocVariadicType() { return getJSDocUnaryTypeUpdateFunction<JSDocVariadicType>(SyntaxKind.JSDocVariadicType); },
|
|
get createJSDocNamepathType() { return getJSDocUnaryTypeCreateFunction<JSDocNamepathType>(SyntaxKind.JSDocNamepathType); },
|
|
get updateJSDocNamepathType() { return getJSDocUnaryTypeUpdateFunction<JSDocNamepathType>(SyntaxKind.JSDocNamepathType); },
|
|
createJSDocFunctionType,
|
|
updateJSDocFunctionType,
|
|
createJSDocTypeLiteral,
|
|
updateJSDocTypeLiteral,
|
|
createJSDocTypeExpression,
|
|
updateJSDocTypeExpression,
|
|
createJSDocSignature,
|
|
updateJSDocSignature,
|
|
createJSDocTemplateTag,
|
|
updateJSDocTemplateTag,
|
|
createJSDocTypedefTag,
|
|
updateJSDocTypedefTag,
|
|
createJSDocParameterTag,
|
|
updateJSDocParameterTag,
|
|
createJSDocPropertyTag,
|
|
updateJSDocPropertyTag,
|
|
createJSDocCallbackTag,
|
|
updateJSDocCallbackTag,
|
|
createJSDocAugmentsTag,
|
|
updateJSDocAugmentsTag,
|
|
createJSDocImplementsTag,
|
|
updateJSDocImplementsTag,
|
|
// lazily load factory members for JSDoc tags with similar structure
|
|
get createJSDocTypeTag() { return getJSDocTypeLikeTagCreateFunction<JSDocTypeTag>(SyntaxKind.JSDocTypeTag); },
|
|
get updateJSDocTypeTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocTypeTag>(SyntaxKind.JSDocTypeTag); },
|
|
get createJSDocReturnTag() { return getJSDocTypeLikeTagCreateFunction<JSDocReturnTag>(SyntaxKind.JSDocReturnTag); },
|
|
get updateJSDocReturnTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocReturnTag>(SyntaxKind.JSDocReturnTag); },
|
|
get createJSDocThisTag() { return getJSDocTypeLikeTagCreateFunction<JSDocThisTag>(SyntaxKind.JSDocThisTag); },
|
|
get updateJSDocThisTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocThisTag>(SyntaxKind.JSDocThisTag); },
|
|
get createJSDocEnumTag() { return getJSDocTypeLikeTagCreateFunction<JSDocEnumTag>(SyntaxKind.JSDocEnumTag); },
|
|
get updateJSDocEnumTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocEnumTag>(SyntaxKind.JSDocEnumTag); },
|
|
get createJSDocAuthorTag() { return getJSDocSimpleTagCreateFunction<JSDocAuthorTag>(SyntaxKind.JSDocAuthorTag); },
|
|
get updateJSDocAuthorTag() { return getJSDocSimpleTagUpdateFunction<JSDocAuthorTag>(SyntaxKind.JSDocAuthorTag); },
|
|
get createJSDocClassTag() { return getJSDocSimpleTagCreateFunction<JSDocClassTag>(SyntaxKind.JSDocClassTag); },
|
|
get updateJSDocClassTag() { return getJSDocSimpleTagUpdateFunction<JSDocClassTag>(SyntaxKind.JSDocClassTag); },
|
|
get createJSDocPublicTag() { return getJSDocSimpleTagCreateFunction<JSDocPublicTag>(SyntaxKind.JSDocPublicTag); },
|
|
get updateJSDocPublicTag() { return getJSDocSimpleTagUpdateFunction<JSDocPublicTag>(SyntaxKind.JSDocPublicTag); },
|
|
get createJSDocPrivateTag() { return getJSDocSimpleTagCreateFunction<JSDocPrivateTag>(SyntaxKind.JSDocPrivateTag); },
|
|
get updateJSDocPrivateTag() { return getJSDocSimpleTagUpdateFunction<JSDocPrivateTag>(SyntaxKind.JSDocPrivateTag); },
|
|
get createJSDocProtectedTag() { return getJSDocSimpleTagCreateFunction<JSDocProtectedTag>(SyntaxKind.JSDocProtectedTag); },
|
|
get updateJSDocProtectedTag() { return getJSDocSimpleTagUpdateFunction<JSDocProtectedTag>(SyntaxKind.JSDocProtectedTag); },
|
|
get createJSDocReadonlyTag() { return getJSDocSimpleTagCreateFunction<JSDocReadonlyTag>(SyntaxKind.JSDocReadonlyTag); },
|
|
get updateJSDocReadonlyTag() { return getJSDocSimpleTagUpdateFunction<JSDocReadonlyTag>(SyntaxKind.JSDocReadonlyTag); },
|
|
get createJSDocDeprecatedTag() { return getJSDocSimpleTagCreateFunction<JSDocDeprecatedTag>(SyntaxKind.JSDocDeprecatedTag); },
|
|
get updateJSDocDeprecatedTag() { return getJSDocSimpleTagUpdateFunction<JSDocDeprecatedTag>(SyntaxKind.JSDocDeprecatedTag); },
|
|
createJSDocUnknownTag,
|
|
updateJSDocUnknownTag,
|
|
createJSDocComment,
|
|
updateJSDocComment,
|
|
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,
|
|
createSourceFile,
|
|
updateSourceFile,
|
|
createBundle,
|
|
updateBundle,
|
|
createUnparsedSource,
|
|
createUnparsedPrologue,
|
|
createUnparsedPrepend,
|
|
createUnparsedTextLike,
|
|
createUnparsedSyntheticReference,
|
|
createInputFiles,
|
|
createSyntheticExpression,
|
|
createSyntaxList,
|
|
createNotEmittedStatement,
|
|
createPartiallyEmittedExpression,
|
|
updatePartiallyEmittedExpression,
|
|
createCommaListExpression,
|
|
updateCommaListExpression,
|
|
createEndOfDeclarationMarker,
|
|
createMergeDeclarationMarker,
|
|
createSyntheticReferenceExpression,
|
|
updateSyntheticReferenceExpression,
|
|
cloneNode,
|
|
|
|
// Lazily load factory methods for common operator factories and utilities
|
|
get createComma() { return getBinaryCreateFunction(SyntaxKind.CommaToken); },
|
|
get createAssignment() { return getBinaryCreateFunction(SyntaxKind.EqualsToken) as NodeFactory["createAssignment"]; },
|
|
get createLogicalOr() { return getBinaryCreateFunction(SyntaxKind.BarBarToken); },
|
|
get createLogicalAnd() { return getBinaryCreateFunction(SyntaxKind.AmpersandAmpersandToken); },
|
|
get createBitwiseOr() { return getBinaryCreateFunction(SyntaxKind.BarToken); },
|
|
get createBitwiseXor() { return getBinaryCreateFunction(SyntaxKind.CaretToken); },
|
|
get createBitwiseAnd() { return getBinaryCreateFunction(SyntaxKind.AmpersandToken); },
|
|
get createStrictEquality() { return getBinaryCreateFunction(SyntaxKind.EqualsEqualsEqualsToken); },
|
|
get createStrictInequality() { return getBinaryCreateFunction(SyntaxKind.ExclamationEqualsEqualsToken); },
|
|
get createEquality() { return getBinaryCreateFunction(SyntaxKind.EqualsEqualsToken); },
|
|
get createInequality() { return getBinaryCreateFunction(SyntaxKind.ExclamationEqualsToken); },
|
|
get createLessThan() { return getBinaryCreateFunction(SyntaxKind.LessThanToken); },
|
|
get createLessThanEquals() { return getBinaryCreateFunction(SyntaxKind.LessThanEqualsToken); },
|
|
get createGreaterThan() { return getBinaryCreateFunction(SyntaxKind.GreaterThanToken); },
|
|
get createGreaterThanEquals() { return getBinaryCreateFunction(SyntaxKind.GreaterThanEqualsToken); },
|
|
get createLeftShift() { return getBinaryCreateFunction(SyntaxKind.LessThanLessThanToken); },
|
|
get createRightShift() { return getBinaryCreateFunction(SyntaxKind.GreaterThanGreaterThanToken); },
|
|
get createUnsignedRightShift() { return getBinaryCreateFunction(SyntaxKind.GreaterThanGreaterThanGreaterThanToken); },
|
|
get createAdd() { return getBinaryCreateFunction(SyntaxKind.PlusToken); },
|
|
get createSubtract() { return getBinaryCreateFunction(SyntaxKind.MinusToken); },
|
|
get createMultiply() { return getBinaryCreateFunction(SyntaxKind.AsteriskToken); },
|
|
get createDivide() { return getBinaryCreateFunction(SyntaxKind.SlashToken); },
|
|
get createModulo() { return getBinaryCreateFunction(SyntaxKind.PercentToken); },
|
|
get createExponent() { return getBinaryCreateFunction(SyntaxKind.AsteriskAsteriskToken); },
|
|
get createPrefixPlus() { return getPrefixUnaryCreateFunction(SyntaxKind.PlusToken); },
|
|
get createPrefixMinus() { return getPrefixUnaryCreateFunction(SyntaxKind.MinusToken); },
|
|
get createPrefixIncrement() { return getPrefixUnaryCreateFunction(SyntaxKind.PlusPlusToken); },
|
|
get createPrefixDecrement() { return getPrefixUnaryCreateFunction(SyntaxKind.MinusMinusToken); },
|
|
get createBitwiseNot() { return getPrefixUnaryCreateFunction(SyntaxKind.TildeToken); },
|
|
get createLogicalNot() { return getPrefixUnaryCreateFunction(SyntaxKind.ExclamationToken); },
|
|
get createPostfixIncrement() { return getPostfixUnaryCreateFunction(SyntaxKind.PlusPlusToken); },
|
|
get createPostfixDecrement() { return getPostfixUnaryCreateFunction(SyntaxKind.MinusMinusToken); },
|
|
|
|
// Compound nodes
|
|
createImmediatelyInvokedFunctionExpression,
|
|
createImmediatelyInvokedArrowFunction,
|
|
createVoidZero,
|
|
createExportDefault,
|
|
createExternalModuleExport,
|
|
createTypeCheck,
|
|
createMethodCall,
|
|
createGlobalMethodCall,
|
|
createFunctionBindCall,
|
|
createFunctionCallCall,
|
|
createFunctionApplyCall,
|
|
createArraySliceCall,
|
|
createArrayConcatCall,
|
|
createObjectDefinePropertyCall,
|
|
createPropertyDescriptor,
|
|
createCallBinding,
|
|
|
|
// Utilities
|
|
inlineExpressions,
|
|
getInternalName,
|
|
getLocalName,
|
|
getExportName,
|
|
getDeclarationName,
|
|
getNamespaceMemberName,
|
|
getExternalModuleOrNamespaceExportName,
|
|
restoreOuterExpressions,
|
|
restoreEnclosingLabel,
|
|
createUseStrictPrologue,
|
|
copyPrologue,
|
|
copyStandardPrologue,
|
|
copyCustomPrologue,
|
|
ensureUseStrict,
|
|
liftToBlock,
|
|
mergeLexicalEnvironment,
|
|
updateModifiers,
|
|
};
|
|
|
|
return factory;
|
|
|
|
// @api
|
|
function createNodeArray<T extends Node>(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray<T> {
|
|
if (elements === undefined || elements === emptyArray) {
|
|
elements = [];
|
|
}
|
|
else if (isNodeArray(elements)) {
|
|
// Ensure the transform flags have been aggregated for this NodeArray
|
|
if (elements.transformFlags === undefined) {
|
|
aggregateChildrenFlags(elements as MutableNodeArray<T>);
|
|
}
|
|
Debug.attachNodeArrayDebugInfo(elements);
|
|
return elements;
|
|
}
|
|
|
|
// Since the element list of a node array is typically created by starting with an empty array and
|
|
// repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for
|
|
// small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation.
|
|
const length = elements.length;
|
|
const array = <MutableNodeArray<T>>(length >= 1 && length <= 4 ? elements.slice() : elements);
|
|
setTextRangePosEnd(array, -1, -1);
|
|
array.hasTrailingComma = !!hasTrailingComma;
|
|
aggregateChildrenFlags(array);
|
|
Debug.attachNodeArrayDebugInfo(array);
|
|
return array;
|
|
}
|
|
|
|
function createBaseNode<T extends Node>(kind: T["kind"]) {
|
|
return baseFactory.createBaseNode(kind) as Mutable<T>;
|
|
}
|
|
|
|
function createBaseDeclaration<T extends Declaration | VariableStatement | ImportDeclaration>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined
|
|
) {
|
|
const node = createBaseNode(kind);
|
|
node.decorators = asNodeArray(decorators);
|
|
node.modifiers = asNodeArray(modifiers);
|
|
node.transformFlags |=
|
|
propagateChildrenFlags(node.decorators) |
|
|
propagateChildrenFlags(node.modifiers);
|
|
// NOTE: The following properties are commonly set by the binder and are added here to
|
|
// ensure declarations have a stable shape.
|
|
node.symbol = undefined!; // initialized by binder
|
|
node.localSymbol = undefined!; // initialized by binder
|
|
node.locals = undefined!; // initialized by binder
|
|
node.nextContainer = undefined!; // initialized by binder
|
|
return node;
|
|
}
|
|
|
|
function createBaseNamedDeclaration<T extends NamedDeclaration>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined
|
|
) {
|
|
const node = createBaseDeclaration(
|
|
kind,
|
|
decorators,
|
|
modifiers
|
|
);
|
|
name = asName(name);
|
|
node.name = name;
|
|
|
|
// The PropertyName of a member is allowed to be `await`.
|
|
// We don't need to exclude `await` for type signatures since types
|
|
// don't propagate child flags.
|
|
if (name) {
|
|
switch (node.kind) {
|
|
case SyntaxKind.MethodDeclaration:
|
|
case SyntaxKind.GetAccessor:
|
|
case SyntaxKind.SetAccessor:
|
|
case SyntaxKind.PropertyDeclaration:
|
|
case SyntaxKind.PropertyAssignment:
|
|
if (isIdentifier(name)) {
|
|
node.transformFlags |= propagateIdentifierNameFlags(name);
|
|
break;
|
|
}
|
|
// fall through
|
|
default:
|
|
node.transformFlags |= propagateChildFlags(name);
|
|
break;
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
function createBaseGenericNamedDeclaration<T extends NamedDeclaration & { typeParameters?: NodeArray<TypeParameterDeclaration> }>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined
|
|
) {
|
|
const node = createBaseNamedDeclaration(
|
|
kind,
|
|
decorators,
|
|
modifiers,
|
|
name
|
|
);
|
|
node.typeParameters = asNodeArray(typeParameters);
|
|
node.transformFlags |= propagateChildrenFlags(node.typeParameters);
|
|
if (typeParameters) node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
function createBaseSignatureDeclaration<T extends SignatureDeclarationBase>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[] | undefined,
|
|
type: TypeNode | undefined
|
|
) {
|
|
const node = createBaseGenericNamedDeclaration(
|
|
kind,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters
|
|
);
|
|
node.parameters = createNodeArray(parameters);
|
|
node.type = type;
|
|
node.transformFlags |=
|
|
propagateChildrenFlags(node.parameters) |
|
|
propagateChildFlags(node.type);
|
|
if (type) node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
function updateBaseSignatureDeclaration<T extends SignatureDeclarationBase>(updated: Mutable<T>, original: T) {
|
|
// copy children used only for error reporting
|
|
if (original.typeArguments) updated.typeArguments = original.typeArguments;
|
|
return update(updated, original);
|
|
}
|
|
|
|
function createBaseFunctionLikeDeclaration<T extends FunctionLikeDeclaration>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[] | undefined,
|
|
type: TypeNode | undefined,
|
|
body: T["body"]
|
|
) {
|
|
const node = createBaseSignatureDeclaration(
|
|
kind,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
parameters,
|
|
type
|
|
);
|
|
node.body = body;
|
|
node.transformFlags |= propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait;
|
|
if (!body) node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
function updateBaseFunctionLikeDeclaration<T extends FunctionLikeDeclaration>(updated: Mutable<T>, original: T) {
|
|
// copy children used only for error reporting
|
|
if (original.exclamationToken) updated.exclamationToken = original.exclamationToken;
|
|
if (original.typeArguments) updated.typeArguments = original.typeArguments;
|
|
return updateBaseSignatureDeclaration(updated, original);
|
|
}
|
|
|
|
function createBaseInterfaceOrClassLikeDeclaration<T extends InterfaceDeclaration | ClassLikeDeclaration>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
heritageClauses: readonly HeritageClause[] | undefined
|
|
) {
|
|
const node = createBaseGenericNamedDeclaration(
|
|
kind,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters
|
|
);
|
|
node.heritageClauses = asNodeArray(heritageClauses);
|
|
node.transformFlags |= propagateChildrenFlags(node.heritageClauses);
|
|
return node;
|
|
}
|
|
|
|
function createBaseClassLikeDeclaration<T extends ClassLikeDeclaration>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
heritageClauses: readonly HeritageClause[] | undefined,
|
|
members: readonly ClassElement[]
|
|
) {
|
|
const node = createBaseInterfaceOrClassLikeDeclaration(
|
|
kind,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
heritageClauses
|
|
);
|
|
node.members = createNodeArray(members);
|
|
node.transformFlags |= propagateChildrenFlags(node.members);
|
|
return node;
|
|
}
|
|
|
|
function createBaseBindingLikeDeclaration<T extends PropertyDeclaration | VariableDeclaration | ParameterDeclaration | BindingElement>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | T["name"] | undefined,
|
|
initializer: Expression | undefined
|
|
) {
|
|
const node = createBaseNamedDeclaration(
|
|
kind,
|
|
decorators,
|
|
modifiers,
|
|
name
|
|
);
|
|
node.initializer = initializer;
|
|
node.transformFlags |= propagateChildFlags(node.initializer);
|
|
return node;
|
|
}
|
|
|
|
function createBaseVariableLikeDeclaration<T extends PropertyDeclaration | VariableDeclaration | ParameterDeclaration>(
|
|
kind: T["kind"],
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | T["name"] | undefined,
|
|
type: TypeNode | undefined,
|
|
initializer: Expression | undefined
|
|
) {
|
|
const node = createBaseBindingLikeDeclaration(
|
|
kind,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
initializer
|
|
);
|
|
node.type = type;
|
|
node.transformFlags |= propagateChildFlags(type);
|
|
if (type) node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
//
|
|
// Literals
|
|
//
|
|
|
|
function createBaseLiteral<T extends LiteralToken>(
|
|
kind: T["kind"],
|
|
text: string
|
|
) {
|
|
const node = createBaseToken(kind);
|
|
node.text = text;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral {
|
|
const node = createBaseLiteral<NumericLiteral>(SyntaxKind.NumericLiteral, typeof value === "number" ? value + "" : value);
|
|
node.numericLiteralFlags = numericLiteralFlags;
|
|
if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) node.transformFlags |= TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral {
|
|
const node = createBaseLiteral<BigIntLiteral>(SyntaxKind.BigIntLiteral, typeof value === "string" ? value : pseudoBigIntToString(value) + "n");
|
|
node.transformFlags |= TransformFlags.ContainsESNext;
|
|
return node;
|
|
}
|
|
|
|
function createBaseStringLiteral(text: string, isSingleQuote?: boolean) {
|
|
const node = createBaseLiteral<StringLiteral>(SyntaxKind.StringLiteral, text);
|
|
node.singleQuote = isSingleQuote;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral {
|
|
const node = createBaseStringLiteral(text, isSingleQuote);
|
|
node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape;
|
|
if (hasExtendedUnicodeEscape) node.transformFlags |= TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createStringLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral {
|
|
const node = createBaseStringLiteral(getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined);
|
|
node.textSourceNode = sourceNode;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createRegularExpressionLiteral(text: string): RegularExpressionLiteral {
|
|
const node = createBaseLiteral<RegularExpressionLiteral>(SyntaxKind.RegularExpressionLiteral, text);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, text: string): LiteralToken {
|
|
switch (kind) {
|
|
case SyntaxKind.NumericLiteral: return createNumericLiteral(text, /*numericLiteralFlags*/ 0);
|
|
case SyntaxKind.BigIntLiteral: return createBigIntLiteral(text);
|
|
case SyntaxKind.StringLiteral: return createStringLiteral(text, /*isSingleQuote*/ undefined);
|
|
case SyntaxKind.JsxText: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ false);
|
|
case SyntaxKind.JsxTextAllWhiteSpaces: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ true);
|
|
case SyntaxKind.RegularExpressionLiteral: return createRegularExpressionLiteral(text);
|
|
case SyntaxKind.NoSubstitutionTemplateLiteral: return createTemplateLiteralLikeNode(kind, text, /*rawText*/ undefined, /*templateFlags*/ 0) as NoSubstitutionTemplateLiteral;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Identifiers
|
|
//
|
|
|
|
function createBaseIdentifier(text: string, originalKeywordKind: SyntaxKind | undefined) {
|
|
if (originalKeywordKind === undefined && text) {
|
|
originalKeywordKind = stringToToken(text);
|
|
}
|
|
if (originalKeywordKind === SyntaxKind.Identifier) {
|
|
originalKeywordKind = undefined;
|
|
}
|
|
const node = baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as Mutable<Identifier>;
|
|
node.originalKeywordKind = originalKeywordKind;
|
|
node.escapedText = escapeLeadingUnderscores(text);
|
|
return node;
|
|
}
|
|
|
|
function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags) {
|
|
const node = createBaseIdentifier(text, /*originalKeywordKind*/ undefined) as Mutable<GeneratedIdentifier>;
|
|
node.autoGenerateFlags = autoGenerateFlags;
|
|
node.autoGenerateId = nextAutoGenerateId;
|
|
nextAutoGenerateId++;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind): Identifier {
|
|
const node = createBaseIdentifier(text, originalKeywordKind);
|
|
if (typeArguments) {
|
|
// NOTE: we do not use `setChildren` here because typeArguments in an identifier do not contribute to transformations
|
|
node.typeArguments = createNodeArray(typeArguments);
|
|
}
|
|
if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) {
|
|
node.transformFlags |= TransformFlags.ContainsPossibleTopLevelAwait;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateIdentifier(node: Identifier, typeArguments?: NodeArray<TypeNode | TypeParameterDeclaration> | undefined): Identifier {
|
|
return node.typeArguments !== typeArguments
|
|
? update(createIdentifier(idText(node), typeArguments), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean): GeneratedIdentifier {
|
|
let flags = GeneratedIdentifierFlags.Auto;
|
|
if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes;
|
|
const name = createBaseGeneratedIdentifier("", flags);
|
|
if (recordTempVariable) {
|
|
recordTempVariable(name);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
/** Create a unique temporary variable for use in a loop. */
|
|
// @api
|
|
function createLoopVariable(): Identifier {
|
|
return createBaseGeneratedIdentifier("", GeneratedIdentifierFlags.Loop);
|
|
}
|
|
|
|
/** Create a unique name based on the supplied text. */
|
|
// @api
|
|
function createUniqueName(text: string, flags: GeneratedIdentifierFlags = GeneratedIdentifierFlags.None): Identifier {
|
|
Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags");
|
|
Debug.assert((flags & (GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)) !== GeneratedIdentifierFlags.FileLevel, "GeneratedIdentifierFlags.FileLevel cannot be set without also setting GeneratedIdentifierFlags.Optimistic");
|
|
return createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | flags);
|
|
}
|
|
|
|
/** Create a unique name generated for a node. */
|
|
// @api
|
|
function getGeneratedNameForNode(node: Node | undefined, flags: GeneratedIdentifierFlags = 0): Identifier {
|
|
Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags");
|
|
const name = createBaseGeneratedIdentifier(node && isIdentifier(node) ? idText(node) : "", GeneratedIdentifierFlags.Node | flags);
|
|
name.original = node;
|
|
return name;
|
|
}
|
|
|
|
// @api
|
|
function createPrivateIdentifier(text: string): PrivateIdentifier {
|
|
if (!startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text);
|
|
const node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as Mutable<PrivateIdentifier>;
|
|
node.escapedText = escapeLeadingUnderscores(text);
|
|
node.transformFlags |= TransformFlags.ContainsClassFields;
|
|
return node;
|
|
}
|
|
|
|
//
|
|
// Punctuation
|
|
//
|
|
|
|
function createBaseToken<T extends Node>(kind: T["kind"]) {
|
|
return baseFactory.createBaseTokenNode(kind) as Mutable<T>;
|
|
}
|
|
|
|
// @api
|
|
function createToken(token: SyntaxKind.SuperKeyword): SuperExpression;
|
|
function createToken(token: SyntaxKind.ThisKeyword): ThisExpression;
|
|
function createToken(token: SyntaxKind.NullKeyword): NullLiteral;
|
|
function createToken(token: SyntaxKind.TrueKeyword): TrueLiteral;
|
|
function createToken(token: SyntaxKind.FalseKeyword): FalseLiteral;
|
|
function createToken<TKind extends PunctuationSyntaxKind>(token: TKind): PunctuationToken<TKind>;
|
|
function createToken<TKind extends KeywordTypeSyntaxKind>(token: TKind): KeywordTypeNode<TKind>;
|
|
function createToken<TKind extends ModifierSyntaxKind>(token: TKind): ModifierToken<TKind>;
|
|
function createToken<TKind extends KeywordSyntaxKind>(token: TKind): KeywordToken<TKind>;
|
|
function createToken<TKind extends SyntaxKind.Unknown | SyntaxKind.EndOfFileToken>(token: TKind): Token<TKind>;
|
|
function createToken<TKind extends SyntaxKind>(token: TKind): Token<TKind>;
|
|
function createToken<TKind extends SyntaxKind>(token: TKind) {
|
|
Debug.assert(token >= SyntaxKind.FirstToken && token <= SyntaxKind.LastToken, "Invalid token");
|
|
Debug.assert(token <= SyntaxKind.FirstTemplateToken || token >= SyntaxKind.LastTemplateToken, "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals.");
|
|
Debug.assert(token <= SyntaxKind.FirstLiteralToken || token >= SyntaxKind.LastLiteralToken, "Invalid token. Use 'createLiteralLikeNode' to create literals.");
|
|
Debug.assert(token !== SyntaxKind.Identifier, "Invalid token. Use 'createIdentifier' to create identifiers");
|
|
const node = createBaseToken<Token<TKind>>(token);
|
|
let transformFlags = TransformFlags.None;
|
|
switch (token) {
|
|
case SyntaxKind.AsyncKeyword:
|
|
// 'async' modifier is ES2017 (async functions) or ES2018 (async generators)
|
|
transformFlags =
|
|
TransformFlags.ContainsES2017 |
|
|
TransformFlags.ContainsES2018;
|
|
break;
|
|
|
|
case SyntaxKind.PublicKeyword:
|
|
case SyntaxKind.PrivateKeyword:
|
|
case SyntaxKind.ProtectedKeyword:
|
|
case SyntaxKind.ReadonlyKeyword:
|
|
case SyntaxKind.AbstractKeyword:
|
|
case SyntaxKind.DeclareKeyword:
|
|
case SyntaxKind.ConstKeyword:
|
|
case SyntaxKind.AnyKeyword:
|
|
case SyntaxKind.NumberKeyword:
|
|
case SyntaxKind.BigIntKeyword:
|
|
case SyntaxKind.NeverKeyword:
|
|
case SyntaxKind.ObjectKeyword:
|
|
case SyntaxKind.StringKeyword:
|
|
case SyntaxKind.BooleanKeyword:
|
|
case SyntaxKind.SymbolKeyword:
|
|
case SyntaxKind.VoidKeyword:
|
|
case SyntaxKind.UnknownKeyword:
|
|
case SyntaxKind.UndefinedKeyword: // `undefined` is an Identifier in the expression case.
|
|
transformFlags = TransformFlags.ContainsTypeScript;
|
|
break;
|
|
case SyntaxKind.StaticKeyword:
|
|
case SyntaxKind.SuperKeyword:
|
|
transformFlags = TransformFlags.ContainsES2015;
|
|
break;
|
|
case SyntaxKind.ThisKeyword:
|
|
// 'this' indicates a lexical 'this'
|
|
transformFlags = TransformFlags.ContainsLexicalThis;
|
|
break;
|
|
}
|
|
if (transformFlags) {
|
|
node.transformFlags |= transformFlags;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
//
|
|
// Reserved words
|
|
//
|
|
|
|
// @api
|
|
function createSuper() {
|
|
return createToken(SyntaxKind.SuperKeyword);
|
|
}
|
|
|
|
// @api
|
|
function createThis() {
|
|
return createToken(SyntaxKind.ThisKeyword);
|
|
}
|
|
|
|
// @api
|
|
function createNull() {
|
|
return createToken(SyntaxKind.NullKeyword);
|
|
}
|
|
|
|
// @api
|
|
function createTrue() {
|
|
return createToken(SyntaxKind.TrueKeyword);
|
|
}
|
|
|
|
// @api
|
|
function createFalse() {
|
|
return createToken(SyntaxKind.FalseKeyword);
|
|
}
|
|
|
|
//
|
|
// Modifiers
|
|
//
|
|
|
|
// @api
|
|
function createModifier<T extends ModifierSyntaxKind>(kind: T) {
|
|
return createToken(kind);
|
|
}
|
|
|
|
// @api
|
|
function createModifiersFromModifierFlags(flags: ModifierFlags) {
|
|
const result: Modifier[] = [];
|
|
if (flags & ModifierFlags.Export) { result.push(createModifier(SyntaxKind.ExportKeyword)); }
|
|
if (flags & ModifierFlags.Ambient) { result.push(createModifier(SyntaxKind.DeclareKeyword)); }
|
|
if (flags & ModifierFlags.Default) { result.push(createModifier(SyntaxKind.DefaultKeyword)); }
|
|
if (flags & ModifierFlags.Const) { result.push(createModifier(SyntaxKind.ConstKeyword)); }
|
|
if (flags & ModifierFlags.Public) { result.push(createModifier(SyntaxKind.PublicKeyword)); }
|
|
if (flags & ModifierFlags.Private) { result.push(createModifier(SyntaxKind.PrivateKeyword)); }
|
|
if (flags & ModifierFlags.Protected) { result.push(createModifier(SyntaxKind.ProtectedKeyword)); }
|
|
if (flags & ModifierFlags.Abstract) { result.push(createModifier(SyntaxKind.AbstractKeyword)); }
|
|
if (flags & ModifierFlags.Static) { result.push(createModifier(SyntaxKind.StaticKeyword)); }
|
|
if (flags & ModifierFlags.Readonly) { result.push(createModifier(SyntaxKind.ReadonlyKeyword)); }
|
|
if (flags & ModifierFlags.Async) { result.push(createModifier(SyntaxKind.AsyncKeyword)); }
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Names
|
|
//
|
|
|
|
// @api
|
|
function createQualifiedName(left: EntityName, right: string | Identifier) {
|
|
const node = createBaseNode<QualifiedName>(SyntaxKind.QualifiedName);
|
|
node.left = left;
|
|
node.right = asName(right);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.left) |
|
|
propagateIdentifierNameFlags(node.right);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) {
|
|
return node.left !== left
|
|
|| node.right !== right
|
|
? update(createQualifiedName(left, right), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createComputedPropertyName(expression: Expression) {
|
|
const node = createBaseNode<ComputedPropertyName>(SyntaxKind.ComputedPropertyName);
|
|
node.expression = parenthesizerRules().parenthesizeExpressionOfComputedPropertyName(expression);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsES2015 |
|
|
TransformFlags.ContainsComputedPropertyName;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createComputedPropertyName(expression), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Signature elements
|
|
//
|
|
|
|
// @api
|
|
function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode) {
|
|
const node = createBaseNamedDeclaration<TypeParameterDeclaration>(
|
|
SyntaxKind.TypeParameter,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
name
|
|
);
|
|
node.constraint = constraint;
|
|
node.default = defaultType;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypeParameterDeclaration(node: TypeParameterDeclaration, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) {
|
|
return node.name !== name
|
|
|| node.constraint !== constraint
|
|
|| node.default !== defaultType
|
|
? update(createTypeParameterDeclaration(name, constraint, defaultType), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createParameterDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
dotDotDotToken: DotDotDotToken | undefined,
|
|
name: string | BindingName,
|
|
questionToken?: QuestionToken,
|
|
type?: TypeNode,
|
|
initializer?: Expression
|
|
) {
|
|
const node = createBaseVariableLikeDeclaration<ParameterDeclaration>(
|
|
SyntaxKind.Parameter,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
type,
|
|
initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer)
|
|
);
|
|
node.dotDotDotToken = dotDotDotToken;
|
|
node.questionToken = questionToken;
|
|
if (isThisIdentifier(node.name)) {
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
}
|
|
else {
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.dotDotDotToken) |
|
|
propagateChildFlags(node.questionToken);
|
|
if (questionToken) node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
if (modifiersToFlags(node.modifiers) & ModifierFlags.ParameterPropertyModifier) node.transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax;
|
|
if (initializer || dotDotDotToken) node.transformFlags |= TransformFlags.ContainsES2015;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateParameterDeclaration(
|
|
node: ParameterDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
dotDotDotToken: DotDotDotToken | undefined,
|
|
name: string | BindingName,
|
|
questionToken: QuestionToken | undefined,
|
|
type: TypeNode | undefined,
|
|
initializer: Expression | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.dotDotDotToken !== dotDotDotToken
|
|
|| node.name !== name
|
|
|| node.questionToken !== questionToken
|
|
|| node.type !== type
|
|
|| node.initializer !== initializer
|
|
? update(createParameterDeclaration(decorators, modifiers, dotDotDotToken, name, questionToken, type, initializer), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createDecorator(expression: Expression) {
|
|
const node = createBaseNode<Decorator>(SyntaxKind.Decorator);
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsTypeScript |
|
|
TransformFlags.ContainsTypeScriptClassSyntax;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateDecorator(node: Decorator, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createDecorator(expression), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Type Elements
|
|
//
|
|
|
|
// @api
|
|
function createPropertySignature(
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: PropertyName | string,
|
|
questionToken: QuestionToken | undefined,
|
|
type: TypeNode | undefined
|
|
): PropertySignature {
|
|
const node = createBaseNamedDeclaration<PropertySignature>(
|
|
SyntaxKind.PropertySignature,
|
|
/*decorators*/ undefined,
|
|
modifiers,
|
|
name
|
|
);
|
|
node.type = type;
|
|
node.questionToken = questionToken;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updatePropertySignature(
|
|
node: PropertySignature,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: PropertyName,
|
|
questionToken: QuestionToken | undefined,
|
|
type: TypeNode | undefined
|
|
) {
|
|
return node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.questionToken !== questionToken
|
|
|| node.type !== type
|
|
? update(createPropertySignature(modifiers, name, questionToken, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createPropertyDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | PropertyName,
|
|
questionOrExclamationToken: QuestionToken | ExclamationToken | undefined,
|
|
type: TypeNode | undefined,
|
|
initializer: Expression | undefined
|
|
) {
|
|
const node = createBaseVariableLikeDeclaration<PropertyDeclaration>(
|
|
SyntaxKind.PropertyDeclaration,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
type,
|
|
initializer
|
|
);
|
|
node.questionToken = questionOrExclamationToken && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined;
|
|
node.exclamationToken = questionOrExclamationToken && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.questionToken) |
|
|
propagateChildFlags(node.exclamationToken) |
|
|
TransformFlags.ContainsClassFields;
|
|
if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax;
|
|
}
|
|
if (questionOrExclamationToken || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updatePropertyDeclaration(
|
|
node: PropertyDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | PropertyName,
|
|
questionOrExclamationToken: QuestionToken | ExclamationToken | undefined,
|
|
type: TypeNode | undefined,
|
|
initializer: Expression | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.questionToken !== (questionOrExclamationToken !== undefined && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined)
|
|
|| node.exclamationToken !== (questionOrExclamationToken !== undefined && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined)
|
|
|| node.type !== type
|
|
|| node.initializer !== initializer
|
|
? update(createPropertyDeclaration(decorators, modifiers, name, questionOrExclamationToken, type, initializer), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createMethodSignature(
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | PropertyName,
|
|
questionToken: QuestionToken | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined
|
|
) {
|
|
const node = createBaseSignatureDeclaration<MethodSignature>(
|
|
SyntaxKind.MethodSignature,
|
|
/*decorators*/ undefined,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
parameters,
|
|
type
|
|
);
|
|
node.questionToken = questionToken;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateMethodSignature(
|
|
node: MethodSignature,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: PropertyName,
|
|
questionToken: QuestionToken | undefined,
|
|
typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
|
|
parameters: NodeArray<ParameterDeclaration>,
|
|
type: TypeNode | undefined
|
|
) {
|
|
return node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.questionToken !== questionToken
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
? updateBaseSignatureDeclaration(createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createMethodDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
asteriskToken: AsteriskToken | undefined,
|
|
name: string | PropertyName,
|
|
questionToken: QuestionToken | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
body: Block | undefined
|
|
) {
|
|
const node = createBaseFunctionLikeDeclaration<MethodDeclaration>(
|
|
SyntaxKind.MethodDeclaration,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
parameters,
|
|
type,
|
|
body
|
|
);
|
|
node.asteriskToken = asteriskToken;
|
|
node.questionToken = questionToken;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.asteriskToken) |
|
|
propagateChildFlags(node.questionToken) |
|
|
TransformFlags.ContainsES2015;
|
|
if (questionToken) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
|
|
if (asteriskToken) {
|
|
node.transformFlags |= TransformFlags.ContainsES2018;
|
|
}
|
|
else {
|
|
node.transformFlags |= TransformFlags.ContainsES2017;
|
|
}
|
|
}
|
|
else if (asteriskToken) {
|
|
node.transformFlags |= TransformFlags.ContainsGenerator;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateMethodDeclaration(
|
|
node: MethodDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
asteriskToken: AsteriskToken | undefined,
|
|
name: PropertyName,
|
|
questionToken: QuestionToken | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
body: Block | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.asteriskToken !== asteriskToken
|
|
|| node.name !== name
|
|
|| node.questionToken !== questionToken
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
|| node.body !== body
|
|
? updateBaseFunctionLikeDeclaration(createMethodDeclaration(decorators, modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createConstructorDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
body: Block | undefined
|
|
) {
|
|
const node = createBaseFunctionLikeDeclaration<ConstructorDeclaration>(
|
|
SyntaxKind.Constructor,
|
|
decorators,
|
|
modifiers,
|
|
/*name*/ undefined,
|
|
/*typeParameters*/ undefined,
|
|
parameters,
|
|
/*type*/ undefined,
|
|
body
|
|
);
|
|
node.transformFlags |= TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateConstructorDeclaration(
|
|
node: ConstructorDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
body: Block | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.parameters !== parameters
|
|
|| node.body !== body
|
|
? updateBaseFunctionLikeDeclaration(createConstructorDeclaration(decorators, modifiers, parameters, body), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createGetAccessorDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | PropertyName,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
body: Block | undefined
|
|
) {
|
|
return createBaseFunctionLikeDeclaration<GetAccessorDeclaration>(
|
|
SyntaxKind.GetAccessor,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
/*typeParameters*/ undefined,
|
|
parameters,
|
|
type,
|
|
body
|
|
);
|
|
}
|
|
|
|
// @api
|
|
function updateGetAccessorDeclaration(
|
|
node: GetAccessorDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: PropertyName,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
body: Block | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
|| node.body !== body
|
|
? updateBaseFunctionLikeDeclaration(createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createSetAccessorDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | PropertyName,
|
|
parameters: readonly ParameterDeclaration[],
|
|
body: Block | undefined
|
|
) {
|
|
return createBaseFunctionLikeDeclaration<SetAccessorDeclaration>(
|
|
SyntaxKind.SetAccessor,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
/*typeParameters*/ undefined,
|
|
parameters,
|
|
/*type*/ undefined,
|
|
body
|
|
);
|
|
}
|
|
|
|
// @api
|
|
function updateSetAccessorDeclaration(
|
|
node: SetAccessorDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: PropertyName,
|
|
parameters: readonly ParameterDeclaration[],
|
|
body: Block | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.parameters !== parameters
|
|
|| node.body !== body
|
|
? updateBaseFunctionLikeDeclaration(createSetAccessorDeclaration(decorators, modifiers, name, parameters, body), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createCallSignature(
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined
|
|
): CallSignatureDeclaration {
|
|
const node = createBaseSignatureDeclaration<CallSignatureDeclaration>(
|
|
SyntaxKind.CallSignature,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
/*name*/ undefined,
|
|
typeParameters,
|
|
parameters,
|
|
type
|
|
);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateCallSignature(
|
|
node: CallSignatureDeclaration,
|
|
typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
|
|
parameters: NodeArray<ParameterDeclaration>,
|
|
type: TypeNode | undefined
|
|
) {
|
|
return node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
? updateBaseSignatureDeclaration(createCallSignature(typeParameters, parameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createConstructSignature(
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined
|
|
): ConstructSignatureDeclaration {
|
|
const node = createBaseSignatureDeclaration<ConstructSignatureDeclaration>(
|
|
SyntaxKind.ConstructSignature,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
/*name*/ undefined,
|
|
typeParameters,
|
|
parameters,
|
|
type
|
|
);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateConstructSignature(
|
|
node: ConstructSignatureDeclaration,
|
|
typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
|
|
parameters: NodeArray<ParameterDeclaration>,
|
|
type: TypeNode | undefined
|
|
) {
|
|
return node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
? updateBaseSignatureDeclaration(createConstructSignature(typeParameters, parameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createIndexSignature(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined
|
|
): IndexSignatureDeclaration {
|
|
const node = createBaseSignatureDeclaration<IndexSignatureDeclaration>(
|
|
SyntaxKind.IndexSignature,
|
|
decorators,
|
|
modifiers,
|
|
/*name*/ undefined,
|
|
/*typeParameters*/ undefined,
|
|
parameters,
|
|
type
|
|
);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateIndexSignature(
|
|
node: IndexSignatureDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode
|
|
) {
|
|
return node.parameters !== parameters
|
|
|| node.type !== type
|
|
|| node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
? updateBaseSignatureDeclaration(createIndexSignature(decorators, modifiers, parameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
// @api
|
|
function createKeywordTypeNode<TKind extends KeywordTypeSyntaxKind>(kind: TKind) {
|
|
return createToken(kind);
|
|
}
|
|
|
|
// @api
|
|
function createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined) {
|
|
const node = createBaseNode<TypePredicateNode>(SyntaxKind.TypePredicate);
|
|
node.assertsModifier = assertsModifier;
|
|
node.parameterName = asName(parameterName);
|
|
node.type = type;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) {
|
|
return node.assertsModifier !== assertsModifier
|
|
|| node.parameterName !== parameterName
|
|
|| node.type !== type
|
|
? update(createTypePredicateNode(assertsModifier, parameterName, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) {
|
|
const node = createBaseNode<TypeReferenceNode>(SyntaxKind.TypeReference);
|
|
node.typeName = asName(typeName);
|
|
node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(createNodeArray(typeArguments));
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined) {
|
|
return node.typeName !== typeName
|
|
|| node.typeArguments !== typeArguments
|
|
? update(createTypeReferenceNode(typeName, typeArguments), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createFunctionTypeNode(
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined
|
|
): FunctionTypeNode {
|
|
const node = createBaseSignatureDeclaration<FunctionTypeNode>(
|
|
SyntaxKind.FunctionType,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
/*name*/ undefined,
|
|
typeParameters,
|
|
parameters,
|
|
type
|
|
);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateFunctionTypeNode(
|
|
node: FunctionTypeNode,
|
|
typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
|
|
parameters: NodeArray<ParameterDeclaration>,
|
|
type: TypeNode | undefined
|
|
) {
|
|
return node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
? updateBaseSignatureDeclaration(createFunctionTypeNode(typeParameters, parameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createConstructorTypeNode(
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined
|
|
): ConstructorTypeNode {
|
|
const node = createBaseSignatureDeclaration<ConstructorTypeNode>(
|
|
SyntaxKind.ConstructorType,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
/*name*/ undefined,
|
|
typeParameters,
|
|
parameters,
|
|
type
|
|
);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateConstructorTypeNode(
|
|
node: ConstructorTypeNode,
|
|
typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
|
|
parameters: NodeArray<ParameterDeclaration>,
|
|
type: TypeNode | undefined
|
|
) {
|
|
return node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
? updateBaseSignatureDeclaration(createConstructorTypeNode(typeParameters, parameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTypeQueryNode(exprName: EntityName) {
|
|
const node = createBaseNode<TypeQueryNode>(SyntaxKind.TypeQuery);
|
|
node.exprName = exprName;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName) {
|
|
return node.exprName !== exprName
|
|
? update(createTypeQueryNode(exprName), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTypeLiteralNode(members: readonly TypeElement[] | undefined) {
|
|
const node = createBaseNode<TypeLiteralNode>(SyntaxKind.TypeLiteral);
|
|
node.members = createNodeArray(members);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray<TypeElement>) {
|
|
return node.members !== members
|
|
? update(createTypeLiteralNode(members), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createArrayTypeNode(elementType: TypeNode) {
|
|
const node = createBaseNode<ArrayTypeNode>(SyntaxKind.ArrayType);
|
|
node.elementType = parenthesizerRules().parenthesizeElementTypeOfArrayType(elementType);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode {
|
|
return node.elementType !== elementType
|
|
? update(createArrayTypeNode(elementType), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]) {
|
|
const node = createBaseNode<TupleTypeNode>(SyntaxKind.TupleType);
|
|
node.elements = createNodeArray(elements);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTupleTypeNode(node: TupleTypeNode, elements: readonly (TypeNode | NamedTupleMember)[]) {
|
|
return node.elements !== elements
|
|
? update(createTupleTypeNode(elements), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) {
|
|
const node = createBaseNode<NamedTupleMember>(SyntaxKind.NamedTupleMember);
|
|
node.dotDotDotToken = dotDotDotToken;
|
|
node.name = name;
|
|
node.questionToken = questionToken;
|
|
node.type = type;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNamedTupleMember(node: NamedTupleMember, dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) {
|
|
return node.dotDotDotToken !== dotDotDotToken
|
|
|| node.name !== name
|
|
|| node.questionToken !== questionToken
|
|
|| node.type !== type
|
|
? update(createNamedTupleMember(dotDotDotToken, name, questionToken, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createOptionalTypeNode(type: TypeNode) {
|
|
const node = createBaseNode<OptionalTypeNode>(SyntaxKind.OptionalType);
|
|
node.type = parenthesizerRules().parenthesizeElementTypeOfArrayType(type);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode {
|
|
return node.type !== type
|
|
? update(createOptionalTypeNode(type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createRestTypeNode(type: TypeNode) {
|
|
const node = createBaseNode<RestTypeNode>(SyntaxKind.RestType);
|
|
node.type = type;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode {
|
|
return node.type !== type
|
|
? update(createRestTypeNode(type), node)
|
|
: node;
|
|
}
|
|
|
|
function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[]) {
|
|
const node = createBaseNode<UnionTypeNode | IntersectionTypeNode>(kind);
|
|
node.types = parenthesizerRules().parenthesizeConstituentTypesOfUnionOrIntersectionType(types);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
function updateUnionOrIntersectionTypeNode<T extends UnionOrIntersectionTypeNode>(node: T, types: NodeArray<TypeNode>): T {
|
|
return node.types !== types
|
|
? update(<T>createUnionOrIntersectionTypeNode(node.kind, types), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode {
|
|
return <UnionTypeNode>createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types);
|
|
}
|
|
|
|
// @api
|
|
function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray<TypeNode>) {
|
|
return updateUnionOrIntersectionTypeNode(node, types);
|
|
}
|
|
|
|
// @api
|
|
function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode {
|
|
return <IntersectionTypeNode>createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types);
|
|
}
|
|
|
|
// @api
|
|
function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray<TypeNode>) {
|
|
return updateUnionOrIntersectionTypeNode(node, types);
|
|
}
|
|
|
|
// @api
|
|
function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) {
|
|
const node = createBaseNode<ConditionalTypeNode>(SyntaxKind.ConditionalType);
|
|
node.checkType = parenthesizerRules().parenthesizeMemberOfConditionalType(checkType);
|
|
node.extendsType = parenthesizerRules().parenthesizeMemberOfConditionalType(extendsType);
|
|
node.trueType = trueType;
|
|
node.falseType = falseType;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) {
|
|
return node.checkType !== checkType
|
|
|| node.extendsType !== extendsType
|
|
|| node.trueType !== trueType
|
|
|| node.falseType !== falseType
|
|
? update(createConditionalTypeNode(checkType, extendsType, trueType, falseType), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createInferTypeNode(typeParameter: TypeParameterDeclaration) {
|
|
const node = createBaseNode<InferTypeNode>(SyntaxKind.InferType);
|
|
node.typeParameter = typeParameter;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration) {
|
|
return node.typeParameter !== typeParameter
|
|
? update(createInferTypeNode(typeParameter), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createImportTypeNode(argument: TypeNode, qualifier?: EntityName, typeArguments?: readonly TypeNode[], isTypeOf = false) {
|
|
const node = createBaseNode<ImportTypeNode>(SyntaxKind.ImportType);
|
|
node.argument = argument;
|
|
node.qualifier = qualifier;
|
|
node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments);
|
|
node.isTypeOf = isTypeOf;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateImportTypeNode(node: ImportTypeNode, argument: TypeNode, qualifier: EntityName | undefined, typeArguments: readonly TypeNode[] | undefined, isTypeOf = node.isTypeOf) {
|
|
return node.argument !== argument
|
|
|| node.qualifier !== qualifier
|
|
|| node.typeArguments !== typeArguments
|
|
|| node.isTypeOf !== isTypeOf
|
|
? update(createImportTypeNode(argument, qualifier, typeArguments, isTypeOf), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createParenthesizedType(type: TypeNode) {
|
|
const node = createBaseNode<ParenthesizedTypeNode>(SyntaxKind.ParenthesizedType);
|
|
node.type = type;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode) {
|
|
return node.type !== type
|
|
? update(createParenthesizedType(type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createThisTypeNode() {
|
|
const node = createBaseNode<ThisTypeNode>(SyntaxKind.ThisType);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode {
|
|
const node = createBaseNode<TypeOperatorNode>(SyntaxKind.TypeOperator);
|
|
node.operator = operator;
|
|
node.type = parenthesizerRules().parenthesizeMemberOfElementType(type);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode) {
|
|
return node.type !== type
|
|
? update(createTypeOperatorNode(node.operator, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) {
|
|
const node = createBaseNode<IndexedAccessTypeNode>(SyntaxKind.IndexedAccessType);
|
|
node.objectType = parenthesizerRules().parenthesizeMemberOfElementType(objectType);
|
|
node.indexType = indexType;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) {
|
|
return node.objectType !== objectType
|
|
|| node.indexType !== indexType
|
|
? update(createIndexedAccessTypeNode(objectType, indexType), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode {
|
|
const node = createBaseNode<MappedTypeNode>(SyntaxKind.MappedType);
|
|
node.readonlyToken = readonlyToken;
|
|
node.typeParameter = typeParameter;
|
|
node.questionToken = questionToken;
|
|
node.type = type;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined): MappedTypeNode {
|
|
return node.readonlyToken !== readonlyToken
|
|
|| node.typeParameter !== typeParameter
|
|
|| node.questionToken !== questionToken
|
|
|| node.type !== type
|
|
? update(createMappedTypeNode(readonlyToken, typeParameter, questionToken, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createLiteralTypeNode(literal: LiteralTypeNode["literal"]) {
|
|
const node = createBaseNode<LiteralTypeNode>(SyntaxKind.LiteralType);
|
|
node.literal = literal;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]) {
|
|
return node.literal !== literal
|
|
? update(createLiteralTypeNode(literal), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Binding Patterns
|
|
//
|
|
|
|
// @api
|
|
function createObjectBindingPattern(elements: readonly BindingElement[]) {
|
|
const node = createBaseNode<ObjectBindingPattern>(SyntaxKind.ObjectBindingPattern);
|
|
node.elements = createNodeArray(elements);
|
|
node.transformFlags |=
|
|
propagateChildrenFlags(node.elements) |
|
|
TransformFlags.ContainsES2015 |
|
|
TransformFlags.ContainsBindingPattern;
|
|
if (node.transformFlags & TransformFlags.ContainsRestOrSpread) {
|
|
node.transformFlags |=
|
|
TransformFlags.ContainsES2018 |
|
|
TransformFlags.ContainsObjectRestOrSpread;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]) {
|
|
return node.elements !== elements
|
|
? update(createObjectBindingPattern(elements), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) {
|
|
const node = createBaseNode<ArrayBindingPattern>(SyntaxKind.ArrayBindingPattern);
|
|
node.elements = createNodeArray(elements);
|
|
node.transformFlags |=
|
|
propagateChildrenFlags(node.elements) |
|
|
TransformFlags.ContainsES2015 |
|
|
TransformFlags.ContainsBindingPattern;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) {
|
|
return node.elements !== elements
|
|
? update(createArrayBindingPattern(elements), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) {
|
|
const node = createBaseBindingLikeDeclaration<BindingElement>(
|
|
SyntaxKind.BindingElement,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
name,
|
|
initializer
|
|
);
|
|
node.propertyName = asName(propertyName);
|
|
node.dotDotDotToken = dotDotDotToken;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.dotDotDotToken) |
|
|
TransformFlags.ContainsES2015;
|
|
if (node.propertyName) {
|
|
node.transformFlags |= isIdentifier(node.propertyName) ?
|
|
propagateIdentifierNameFlags(node.propertyName) :
|
|
propagateChildFlags(node.propertyName);
|
|
}
|
|
if (dotDotDotToken) node.transformFlags |= TransformFlags.ContainsRestOrSpread;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined) {
|
|
return node.propertyName !== propertyName
|
|
|| node.dotDotDotToken !== dotDotDotToken
|
|
|| node.name !== name
|
|
|| node.initializer !== initializer
|
|
? update(createBindingElement(dotDotDotToken, propertyName, name, initializer), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Expression
|
|
//
|
|
|
|
function createBaseExpression<T extends Expression>(kind: T["kind"]) {
|
|
const node = createBaseNode(kind);
|
|
// the following properties are commonly set by the checker/binder
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean) {
|
|
const node = createBaseExpression<ArrayLiteralExpression>(SyntaxKind.ArrayLiteralExpression);
|
|
node.elements = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(elements));
|
|
node.multiLine = multiLine;
|
|
node.transformFlags |= propagateChildrenFlags(node.elements);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]) {
|
|
return node.elements !== elements
|
|
? update(createArrayLiteralExpression(elements, node.multiLine), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean) {
|
|
const node = createBaseExpression<ObjectLiteralExpression>(SyntaxKind.ObjectLiteralExpression);
|
|
node.properties = createNodeArray(properties);
|
|
node.multiLine = multiLine;
|
|
node.transformFlags |= propagateChildrenFlags(node.properties);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) {
|
|
return node.properties !== properties
|
|
? update(createObjectLiteralExpression(properties, node.multiLine), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createPropertyAccessExpression(expression: Expression, name: string | Identifier | PrivateIdentifier) {
|
|
const node = createBaseExpression<PropertyAccessExpression>(SyntaxKind.PropertyAccessExpression);
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.name = asName(name);
|
|
node.transformFlags =
|
|
propagateChildFlags(node.expression) |
|
|
(isIdentifier(node.name) ?
|
|
propagateIdentifierNameFlags(node.name) :
|
|
propagateChildFlags(node.name));
|
|
if (isSuperKeyword(expression)) {
|
|
// super method calls require a lexical 'this'
|
|
// super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators
|
|
node.transformFlags |=
|
|
TransformFlags.ContainsES2017 |
|
|
TransformFlags.ContainsES2018;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateIdentifier) {
|
|
if (isPropertyAccessChain(node)) {
|
|
return updatePropertyAccessChain(node, expression, node.questionDotToken, cast(name, isIdentifier));
|
|
}
|
|
return node.expression !== expression
|
|
|| node.name !== name
|
|
? update(createPropertyAccessExpression(expression, name), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier | PrivateIdentifier) {
|
|
const node = createBaseExpression<PropertyAccessChain>(SyntaxKind.PropertyAccessExpression);
|
|
node.flags |= NodeFlags.OptionalChain;
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.questionDotToken = questionDotToken;
|
|
node.name = asName(name);
|
|
node.transformFlags |=
|
|
TransformFlags.ContainsES2020 |
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.questionDotToken) |
|
|
(isIdentifier(node.name) ?
|
|
propagateIdentifierNameFlags(node.name) :
|
|
propagateChildFlags(node.name));
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier | PrivateIdentifier) {
|
|
Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a PropertyAccessExpression using updatePropertyAccessChain. Use updatePropertyAccess instead.");
|
|
// Because we are updating an existing PropertyAccessChain we want to inherit its emitFlags
|
|
// instead of using the default from createPropertyAccess
|
|
return node.expression !== expression
|
|
|| node.questionDotToken !== questionDotToken
|
|
|| node.name !== name
|
|
? update(createPropertyAccessChain(expression, questionDotToken, name), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createElementAccessExpression(expression: Expression, index: number | Expression) {
|
|
const node = createBaseExpression<ElementAccessExpression>(SyntaxKind.ElementAccessExpression);
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.argumentExpression = asExpression(index);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.argumentExpression);
|
|
if (isSuperKeyword(expression)) {
|
|
// super method calls require a lexical 'this'
|
|
// super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators
|
|
node.transformFlags |=
|
|
TransformFlags.ContainsES2017 |
|
|
TransformFlags.ContainsES2018;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) {
|
|
if (isElementAccessChain(node)) {
|
|
return updateElementAccessChain(node, expression, node.questionDotToken, argumentExpression);
|
|
}
|
|
return node.expression !== expression
|
|
|| node.argumentExpression !== argumentExpression
|
|
? update(createElementAccessExpression(expression, argumentExpression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) {
|
|
const node = createBaseExpression<ElementAccessChain>(SyntaxKind.ElementAccessExpression);
|
|
node.flags |= NodeFlags.OptionalChain;
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.questionDotToken = questionDotToken;
|
|
node.argumentExpression = asExpression(index);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.questionDotToken) |
|
|
propagateChildFlags(node.argumentExpression) |
|
|
TransformFlags.ContainsES2020;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) {
|
|
Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a ElementAccessExpression using updateElementAccessChain. Use updateElementAccess instead.");
|
|
// Because we are updating an existing ElementAccessChain we want to inherit its emitFlags
|
|
// instead of using the default from createElementAccess
|
|
return node.expression !== expression
|
|
|| node.questionDotToken !== questionDotToken
|
|
|| node.argumentExpression !== argumentExpression
|
|
? update(createElementAccessChain(expression, questionDotToken, argumentExpression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) {
|
|
const node = createBaseExpression<CallExpression>(SyntaxKind.CallExpression);
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.typeArguments = asNodeArray(typeArguments);
|
|
node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray));
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildrenFlags(node.typeArguments) |
|
|
propagateChildrenFlags(node.arguments);
|
|
if (node.typeArguments) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
if (isImportKeyword(node.expression)) {
|
|
node.transformFlags |= TransformFlags.ContainsDynamicImport;
|
|
}
|
|
else if (isSuperProperty(node.expression)) {
|
|
node.transformFlags |= TransformFlags.ContainsLexicalThis;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) {
|
|
if (isCallChain(node)) {
|
|
return updateCallChain(node, expression, node.questionDotToken, typeArguments, argumentsArray);
|
|
}
|
|
return node.expression !== expression
|
|
|| node.typeArguments !== typeArguments
|
|
|| node.arguments !== argumentsArray
|
|
? update(createCallExpression(expression, typeArguments, argumentsArray), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) {
|
|
const node = createBaseExpression<CallChain>(SyntaxKind.CallExpression);
|
|
node.flags |= NodeFlags.OptionalChain;
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.questionDotToken = questionDotToken;
|
|
node.typeArguments = asNodeArray(typeArguments);
|
|
node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray));
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.questionDotToken) |
|
|
propagateChildrenFlags(node.typeArguments) |
|
|
propagateChildrenFlags(node.arguments) |
|
|
TransformFlags.ContainsES2020;
|
|
if (node.typeArguments) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
if (isSuperProperty(node.expression)) {
|
|
node.transformFlags |= TransformFlags.ContainsLexicalThis;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) {
|
|
Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a CallExpression using updateCallChain. Use updateCall instead.");
|
|
return node.expression !== expression
|
|
|| node.questionDotToken !== questionDotToken
|
|
|| node.typeArguments !== typeArguments
|
|
|| node.arguments !== argumentsArray
|
|
? update(createCallChain(expression, questionDotToken, typeArguments, argumentsArray), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) {
|
|
const node = createBaseExpression<NewExpression>(SyntaxKind.NewExpression);
|
|
node.expression = parenthesizerRules().parenthesizeExpressionOfNew(expression);
|
|
node.typeArguments = asNodeArray(typeArguments);
|
|
node.arguments = argumentsArray ? parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(argumentsArray) : undefined;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildrenFlags(node.typeArguments) |
|
|
propagateChildrenFlags(node.arguments) |
|
|
TransformFlags.ContainsES2020;
|
|
if (node.typeArguments) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNewExpression(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) {
|
|
return node.expression !== expression
|
|
|| node.typeArguments !== typeArguments
|
|
|| node.arguments !== argumentsArray
|
|
? update(createNewExpression(expression, typeArguments, argumentsArray), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) {
|
|
const node = createBaseExpression<TaggedTemplateExpression>(SyntaxKind.TaggedTemplateExpression);
|
|
node.tag = parenthesizerRules().parenthesizeLeftSideOfAccess(tag);
|
|
node.typeArguments = asNodeArray(typeArguments);
|
|
node.template = template;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.tag) |
|
|
propagateChildrenFlags(node.typeArguments) |
|
|
propagateChildFlags(node.template) |
|
|
TransformFlags.ContainsES2015;
|
|
if (node.typeArguments) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
if (hasInvalidEscape(node.template)) {
|
|
node.transformFlags |= TransformFlags.ContainsES2018;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) {
|
|
return node.tag !== tag
|
|
|| node.typeArguments !== typeArguments
|
|
|| node.template !== template
|
|
? update(createTaggedTemplateExpression(tag, typeArguments, template), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTypeAssertion(type: TypeNode, expression: Expression) {
|
|
const node = createBaseExpression<TypeAssertion>(SyntaxKind.TypeAssertionExpression);
|
|
node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
|
|
node.type = type;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.type) |
|
|
TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) {
|
|
return node.type !== type
|
|
|| node.expression !== expression
|
|
? update(createTypeAssertion(type, expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createParenthesizedExpression(expression: Expression) {
|
|
const node = createBaseExpression<ParenthesizedExpression>(SyntaxKind.ParenthesizedExpression);
|
|
node.expression = expression;
|
|
node.transformFlags = propagateChildFlags(node.expression);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createParenthesizedExpression(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createFunctionExpression(
|
|
modifiers: readonly Modifier[] | undefined,
|
|
asteriskToken: AsteriskToken | undefined,
|
|
name: string | Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[] | undefined,
|
|
type: TypeNode | undefined,
|
|
body: Block
|
|
) {
|
|
const node = createBaseFunctionLikeDeclaration<FunctionExpression>(
|
|
SyntaxKind.FunctionExpression,
|
|
/*decorators*/ undefined,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
parameters,
|
|
type,
|
|
body
|
|
);
|
|
node.asteriskToken = asteriskToken;
|
|
node.transformFlags |= propagateChildFlags(node.asteriskToken);
|
|
if (node.typeParameters) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
|
|
if (node.asteriskToken) {
|
|
node.transformFlags |= TransformFlags.ContainsES2018;
|
|
}
|
|
else {
|
|
node.transformFlags |= TransformFlags.ContainsES2017;
|
|
}
|
|
}
|
|
else if (node.asteriskToken) {
|
|
node.transformFlags |= TransformFlags.ContainsGenerator;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateFunctionExpression(
|
|
node: FunctionExpression,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
asteriskToken: AsteriskToken | undefined,
|
|
name: Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
body: Block
|
|
) {
|
|
return node.name !== name
|
|
|| node.modifiers !== modifiers
|
|
|| node.asteriskToken !== asteriskToken
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
|| node.body !== body
|
|
? updateBaseFunctionLikeDeclaration(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createArrowFunction(
|
|
modifiers: readonly Modifier[] | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
equalsGreaterThanToken: EqualsGreaterThanToken | undefined,
|
|
body: ConciseBody
|
|
) {
|
|
const node = createBaseFunctionLikeDeclaration<ArrowFunction>(
|
|
SyntaxKind.ArrowFunction,
|
|
/*decorators*/ undefined,
|
|
modifiers,
|
|
/*name*/ undefined,
|
|
typeParameters,
|
|
parameters,
|
|
type,
|
|
parenthesizerRules().parenthesizeConciseBodyOfArrowFunction(body)
|
|
);
|
|
node.equalsGreaterThanToken = equalsGreaterThanToken ?? createToken(SyntaxKind.EqualsGreaterThanToken);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.equalsGreaterThanToken) |
|
|
TransformFlags.ContainsES2015;
|
|
if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
|
|
node.transformFlags |= TransformFlags.ContainsES2017;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateArrowFunction(
|
|
node: ArrowFunction,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
equalsGreaterThanToken: EqualsGreaterThanToken,
|
|
body: ConciseBody
|
|
): ArrowFunction {
|
|
return node.modifiers !== modifiers
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
|| node.equalsGreaterThanToken !== equalsGreaterThanToken
|
|
|| node.body !== body
|
|
? updateBaseFunctionLikeDeclaration(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createDeleteExpression(expression: Expression) {
|
|
const node = createBaseExpression<DeleteExpression>(SyntaxKind.DeleteExpression);
|
|
node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
|
|
node.transformFlags |= propagateChildFlags(node.expression);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateDeleteExpression(node: DeleteExpression, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createDeleteExpression(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTypeOfExpression(expression: Expression) {
|
|
const node = createBaseExpression<TypeOfExpression>(SyntaxKind.TypeOfExpression);
|
|
node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
|
|
node.transformFlags |= propagateChildFlags(node.expression);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypeOfExpression(node: TypeOfExpression, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createTypeOfExpression(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createVoidExpression(expression: Expression) {
|
|
const node = createBaseExpression<VoidExpression>(SyntaxKind.VoidExpression);
|
|
node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
|
|
node.transformFlags |= propagateChildFlags(node.expression);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateVoidExpression(node: VoidExpression, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createVoidExpression(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createAwaitExpression(expression: Expression) {
|
|
const node = createBaseExpression<AwaitExpression>(SyntaxKind.AwaitExpression);
|
|
node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsES2017 |
|
|
TransformFlags.ContainsES2018 |
|
|
TransformFlags.ContainsAwait;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateAwaitExpression(node: AwaitExpression, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createAwaitExpression(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createPrefixUnaryExpression(operator: PrefixUnaryOperator, operand: Expression) {
|
|
const node = createBaseExpression<PrefixUnaryExpression>(SyntaxKind.PrefixUnaryExpression);
|
|
node.operator = operator;
|
|
node.operand = parenthesizerRules().parenthesizeOperandOfPrefixUnary(operand);
|
|
node.transformFlags |= propagateChildFlags(node.operand);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression) {
|
|
return node.operand !== operand
|
|
? update(createPrefixUnaryExpression(node.operator, operand), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator) {
|
|
const node = createBaseExpression<PostfixUnaryExpression>(SyntaxKind.PostfixUnaryExpression);
|
|
node.operator = operator;
|
|
node.operand = parenthesizerRules().parenthesizeOperandOfPostfixUnary(operand);
|
|
node.transformFlags = propagateChildFlags(node.operand);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression) {
|
|
return node.operand !== operand
|
|
? update(createPostfixUnaryExpression(operand, node.operator), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) {
|
|
const node = createBaseExpression<BinaryExpression>(SyntaxKind.BinaryExpression);
|
|
const operatorToken = asToken(operator);
|
|
const operatorKind = operatorToken.kind;
|
|
node.left = parenthesizerRules().parenthesizeLeftSideOfBinary(operatorKind, left);
|
|
node.operatorToken = operatorToken;
|
|
node.right = parenthesizerRules().parenthesizeRightSideOfBinary(operatorKind, node.left, right);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.left) |
|
|
propagateChildFlags(node.operatorToken) |
|
|
propagateChildFlags(node.right);
|
|
if (operatorKind === SyntaxKind.QuestionQuestionToken) {
|
|
node.transformFlags |= TransformFlags.ContainsES2020;
|
|
}
|
|
else if (operatorKind === SyntaxKind.EqualsToken) {
|
|
if (isObjectLiteralExpression(node.left)) {
|
|
node.transformFlags |=
|
|
TransformFlags.ContainsES2015 |
|
|
TransformFlags.ContainsES2018 |
|
|
TransformFlags.ContainsDestructuringAssignment;
|
|
}
|
|
else if (isArrayLiteralExpression(node.left)) {
|
|
node.transformFlags |=
|
|
TransformFlags.ContainsES2015 |
|
|
TransformFlags.ContainsDestructuringAssignment;
|
|
}
|
|
}
|
|
else if (operatorKind === SyntaxKind.AsteriskAsteriskToken || operatorKind === SyntaxKind.AsteriskAsteriskEqualsToken) {
|
|
node.transformFlags |= TransformFlags.ContainsES2016;
|
|
}
|
|
else if (isLogicalOrCoalescingAssignmentOperator(operatorKind)) {
|
|
node.transformFlags |= TransformFlags.ContainsESNext;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateBinaryExpression(node: BinaryExpression, left: Expression, operator: BinaryOperatorToken, right: Expression) {
|
|
return node.left !== left
|
|
|| node.operatorToken !== operator
|
|
|| node.right !== right
|
|
? update(createBinaryExpression(left, operator, right), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression) {
|
|
const node = createBaseExpression<ConditionalExpression>(SyntaxKind.ConditionalExpression);
|
|
node.condition = parenthesizerRules().parenthesizeConditionOfConditionalExpression(condition);
|
|
node.questionToken = questionToken ?? createToken(SyntaxKind.QuestionToken);
|
|
node.whenTrue = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenTrue);
|
|
node.colonToken = colonToken ?? createToken(SyntaxKind.ColonToken);
|
|
node.whenFalse = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenFalse);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.condition) |
|
|
propagateChildFlags(node.questionToken) |
|
|
propagateChildFlags(node.whenTrue) |
|
|
propagateChildFlags(node.colonToken) |
|
|
propagateChildFlags(node.whenFalse);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateConditionalExpression(
|
|
node: ConditionalExpression,
|
|
condition: Expression,
|
|
questionToken: Token<SyntaxKind.QuestionToken>,
|
|
whenTrue: Expression,
|
|
colonToken: Token<SyntaxKind.ColonToken>,
|
|
whenFalse: Expression
|
|
): ConditionalExpression {
|
|
return node.condition !== condition
|
|
|| node.questionToken !== questionToken
|
|
|| node.whenTrue !== whenTrue
|
|
|| node.colonToken !== colonToken
|
|
|| node.whenFalse !== whenFalse
|
|
? update(createConditionalExpression(condition, questionToken, whenTrue, colonToken, whenFalse), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]) {
|
|
const node = createBaseExpression<TemplateExpression>(SyntaxKind.TemplateExpression);
|
|
node.head = head;
|
|
node.templateSpans = createNodeArray(templateSpans);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.head) |
|
|
propagateChildrenFlags(node.templateSpans) |
|
|
TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) {
|
|
return node.head !== head
|
|
|| node.templateSpans !== templateSpans
|
|
? update(createTemplateExpression(head, templateSpans), node)
|
|
: node;
|
|
}
|
|
|
|
function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = TokenFlags.None) {
|
|
Debug.assert(!(templateFlags & ~TokenFlags.TemplateLiteralLikeFlags), "Unsupported template flags.");
|
|
// NOTE: without the assignment to `undefined`, we don't narrow the initial type of `cooked`.
|
|
// eslint-disable-next-line no-undef-init
|
|
let cooked: string | object | undefined = undefined;
|
|
if (rawText !== undefined && rawText !== text) {
|
|
cooked = getCookedText(kind, rawText);
|
|
if (typeof cooked === "object") {
|
|
return Debug.fail("Invalid raw text");
|
|
}
|
|
}
|
|
if (text === undefined) {
|
|
if (cooked === undefined) {
|
|
return Debug.fail("Arguments 'text' and 'rawText' may not both be undefined.");
|
|
}
|
|
text = cooked;
|
|
}
|
|
else if (cooked !== undefined) {
|
|
Debug.assert(text === cooked, "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'.");
|
|
}
|
|
return createTemplateLiteralLikeNode(kind, text, rawText, templateFlags);
|
|
}
|
|
|
|
// @api
|
|
function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) {
|
|
const node = createBaseToken<TemplateLiteralLikeNode>(kind);
|
|
node.text = text;
|
|
node.rawText = rawText;
|
|
node.templateFlags = templateFlags! & TokenFlags.TemplateLiteralLikeFlags;
|
|
node.transformFlags |= TransformFlags.ContainsES2015;
|
|
if (node.templateFlags) {
|
|
node.transformFlags |= TransformFlags.ContainsES2018;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createTemplateHead(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) {
|
|
return <TemplateHead>createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateHead, text, rawText, templateFlags);
|
|
}
|
|
|
|
// @api
|
|
function createTemplateMiddle(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) {
|
|
return <TemplateMiddle>createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateMiddle, text, rawText, templateFlags);
|
|
}
|
|
|
|
// @api
|
|
function createTemplateTail(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) {
|
|
return <TemplateTail>createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateTail, text, rawText, templateFlags);
|
|
}
|
|
|
|
// @api
|
|
function createNoSubstitutionTemplateLiteral(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) {
|
|
return <NoSubstitutionTemplateLiteral>createTemplateLiteralLikeNodeChecked(SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText, templateFlags);
|
|
}
|
|
|
|
// @api
|
|
function createYieldExpression(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression {
|
|
Debug.assert(!asteriskToken || !!expression, "A `YieldExpression` with an asteriskToken must have an expression.");
|
|
const node = createBaseExpression<YieldExpression>(SyntaxKind.YieldExpression);
|
|
node.expression = expression && parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
|
|
node.asteriskToken = asteriskToken;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.asteriskToken) |
|
|
TransformFlags.ContainsES2015 |
|
|
TransformFlags.ContainsES2018 |
|
|
TransformFlags.ContainsYield;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) {
|
|
return node.expression !== expression
|
|
|| node.asteriskToken !== asteriskToken
|
|
? update(createYieldExpression(asteriskToken, expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createSpreadElement(expression: Expression) {
|
|
const node = createBaseExpression<SpreadElement>(SyntaxKind.SpreadElement);
|
|
node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsES2015 |
|
|
TransformFlags.ContainsRestOrSpread;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateSpreadElement(node: SpreadElement, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createSpreadElement(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createClassExpression(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
heritageClauses: readonly HeritageClause[] | undefined,
|
|
members: readonly ClassElement[]
|
|
) {
|
|
const node = createBaseClassLikeDeclaration<ClassExpression>(
|
|
SyntaxKind.ClassExpression,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
heritageClauses,
|
|
members
|
|
);
|
|
node.transformFlags |= TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateClassExpression(
|
|
node: ClassExpression,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
heritageClauses: readonly HeritageClause[] | undefined,
|
|
members: readonly ClassElement[]
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.heritageClauses !== heritageClauses
|
|
|| node.members !== members
|
|
? update(createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createOmittedExpression() {
|
|
return createBaseExpression<OmittedExpression>(SyntaxKind.OmittedExpression);
|
|
}
|
|
|
|
// @api
|
|
function createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined) {
|
|
const node = createBaseNode<ExpressionWithTypeArguments>(SyntaxKind.ExpressionWithTypeArguments);
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildrenFlags(node.typeArguments) |
|
|
TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined) {
|
|
return node.expression !== expression
|
|
|| node.typeArguments !== typeArguments
|
|
? update(createExpressionWithTypeArguments(expression, typeArguments), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createAsExpression(expression: Expression, type: TypeNode) {
|
|
const node = createBaseExpression<AsExpression>(SyntaxKind.AsExpression);
|
|
node.expression = expression;
|
|
node.type = type;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.type) |
|
|
TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) {
|
|
return node.expression !== expression
|
|
|| node.type !== type
|
|
? update(createAsExpression(expression, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNonNullExpression(expression: Expression) {
|
|
const node = createBaseExpression<NonNullExpression>(SyntaxKind.NonNullExpression);
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNonNullExpression(node: NonNullExpression, expression: Expression) {
|
|
if (isNonNullChain(node)) {
|
|
return updateNonNullChain(node, expression);
|
|
}
|
|
return node.expression !== expression
|
|
? update(createNonNullExpression(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNonNullChain(expression: Expression) {
|
|
const node = createBaseExpression<NonNullChain>(SyntaxKind.NonNullExpression);
|
|
node.flags |= NodeFlags.OptionalChain;
|
|
node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNonNullChain(node: NonNullChain, expression: Expression) {
|
|
Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a NonNullExpression using updateNonNullChain. Use updateNonNullExpression instead.");
|
|
return node.expression !== expression
|
|
? update(createNonNullChain(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) {
|
|
const node = createBaseExpression<MetaProperty>(SyntaxKind.MetaProperty);
|
|
node.keywordToken = keywordToken;
|
|
node.name = name;
|
|
node.transformFlags |= propagateChildFlags(node.name);
|
|
switch (keywordToken) {
|
|
case SyntaxKind.NewKeyword:
|
|
node.transformFlags |= TransformFlags.ContainsES2015;
|
|
break;
|
|
case SyntaxKind.ImportKeyword:
|
|
node.transformFlags |= TransformFlags.ContainsESNext;
|
|
break;
|
|
default:
|
|
return Debug.assertNever(keywordToken);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateMetaProperty(node: MetaProperty, name: Identifier) {
|
|
return node.name !== name
|
|
? update(createMetaProperty(node.keywordToken, name), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Misc
|
|
//
|
|
|
|
// @api
|
|
function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) {
|
|
const node = createBaseNode<TemplateSpan>(SyntaxKind.TemplateSpan);
|
|
node.expression = expression;
|
|
node.literal = literal;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.literal) |
|
|
TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) {
|
|
return node.expression !== expression
|
|
|| node.literal !== literal
|
|
? update(createTemplateSpan(expression, literal), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createSemicolonClassElement() {
|
|
const node = createBaseNode<SemicolonClassElement>(SyntaxKind.SemicolonClassElement);
|
|
node.transformFlags |= TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
//
|
|
// Element
|
|
//
|
|
|
|
// @api
|
|
function createBlock(statements: readonly Statement[], multiLine?: boolean): Block {
|
|
const node = createBaseNode<Block>(SyntaxKind.Block);
|
|
node.statements = createNodeArray(statements);
|
|
node.multiLine = multiLine;
|
|
node.transformFlags |= propagateChildrenFlags(node.statements);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateBlock(node: Block, statements: readonly Statement[]) {
|
|
return node.statements !== statements
|
|
? update(createBlock(statements, node.multiLine), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) {
|
|
const node = createBaseDeclaration<VariableStatement>(SyntaxKind.VariableStatement, /*decorators*/ undefined, modifiers);
|
|
node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.declarationList);
|
|
if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) {
|
|
return node.modifiers !== modifiers
|
|
|| node.declarationList !== declarationList
|
|
? update(createVariableStatement(modifiers, declarationList), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createEmptyStatement() {
|
|
return createBaseNode<EmptyStatement>(SyntaxKind.EmptyStatement);
|
|
}
|
|
|
|
// @api
|
|
function createExpressionStatement(expression: Expression): ExpressionStatement {
|
|
const node = createBaseNode<ExpressionStatement>(SyntaxKind.ExpressionStatement);
|
|
node.expression = parenthesizerRules().parenthesizeExpressionOfExpressionStatement(expression);
|
|
node.transformFlags |= propagateChildFlags(node.expression);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateExpressionStatement(node: ExpressionStatement, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createExpressionStatement(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement) {
|
|
const node = createBaseNode<IfStatement>(SyntaxKind.IfStatement);
|
|
node.expression = expression;
|
|
node.thenStatement = asEmbeddedStatement(thenStatement);
|
|
node.elseStatement = asEmbeddedStatement(elseStatement);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.thenStatement) |
|
|
propagateChildFlags(node.elseStatement);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) {
|
|
return node.expression !== expression
|
|
|| node.thenStatement !== thenStatement
|
|
|| node.elseStatement !== elseStatement
|
|
? update(createIfStatement(expression, thenStatement, elseStatement), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createDoStatement(statement: Statement, expression: Expression) {
|
|
const node = createBaseNode<DoStatement>(SyntaxKind.DoStatement);
|
|
node.statement = asEmbeddedStatement(statement);
|
|
node.expression = expression;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.statement) |
|
|
propagateChildFlags(node.expression);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateDoStatement(node: DoStatement, statement: Statement, expression: Expression) {
|
|
return node.statement !== statement
|
|
|| node.expression !== expression
|
|
? update(createDoStatement(statement, expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createWhileStatement(expression: Expression, statement: Statement) {
|
|
const node = createBaseNode<WhileStatement>(SyntaxKind.WhileStatement);
|
|
node.expression = expression;
|
|
node.statement = asEmbeddedStatement(statement);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.statement);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement) {
|
|
return node.expression !== expression
|
|
|| node.statement !== statement
|
|
? update(createWhileStatement(expression, statement), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) {
|
|
const node = createBaseNode<ForStatement>(SyntaxKind.ForStatement);
|
|
node.initializer = initializer;
|
|
node.condition = condition;
|
|
node.incrementor = incrementor;
|
|
node.statement = asEmbeddedStatement(statement);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.initializer) |
|
|
propagateChildFlags(node.condition) |
|
|
propagateChildFlags(node.incrementor) |
|
|
propagateChildFlags(node.statement);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateForStatement(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) {
|
|
return node.initializer !== initializer
|
|
|| node.condition !== condition
|
|
|| node.incrementor !== incrementor
|
|
|| node.statement !== statement
|
|
? update(createForStatement(initializer, condition, incrementor, statement), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createForInStatement(initializer: ForInitializer, expression: Expression, statement: Statement) {
|
|
const node = createBaseNode<ForInStatement>(SyntaxKind.ForInStatement);
|
|
node.initializer = initializer;
|
|
node.expression = expression;
|
|
node.statement = asEmbeddedStatement(statement);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.initializer) |
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.statement);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateForInStatement(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) {
|
|
return node.initializer !== initializer
|
|
|| node.expression !== expression
|
|
|| node.statement !== statement
|
|
? update(createForInStatement(initializer, expression, statement), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) {
|
|
const node = createBaseNode<ForOfStatement>(SyntaxKind.ForOfStatement);
|
|
node.awaitModifier = awaitModifier;
|
|
node.initializer = initializer;
|
|
node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
|
|
node.statement = asEmbeddedStatement(statement);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.awaitModifier) |
|
|
propagateChildFlags(node.initializer) |
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.statement) |
|
|
TransformFlags.ContainsES2015;
|
|
if (awaitModifier) node.transformFlags |= TransformFlags.ContainsES2018;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) {
|
|
return node.awaitModifier !== awaitModifier
|
|
|| node.initializer !== initializer
|
|
|| node.expression !== expression
|
|
|| node.statement !== statement
|
|
? update(createForOfStatement(awaitModifier, initializer, expression, statement), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createContinueStatement(label?: string | Identifier): ContinueStatement {
|
|
const node = createBaseNode<ContinueStatement>(SyntaxKind.ContinueStatement);
|
|
node.label = asName(label);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.label) |
|
|
TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateContinueStatement(node: ContinueStatement, label: Identifier | undefined) {
|
|
return node.label !== label
|
|
? update(createContinueStatement(label), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createBreakStatement(label?: string | Identifier): BreakStatement {
|
|
const node = createBaseNode<BreakStatement>(SyntaxKind.BreakStatement);
|
|
node.label = asName(label);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.label) |
|
|
TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateBreakStatement(node: BreakStatement, label: Identifier | undefined) {
|
|
return node.label !== label
|
|
? update(createBreakStatement(label), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createReturnStatement(expression?: Expression): ReturnStatement {
|
|
const node = createBaseNode<ReturnStatement>(SyntaxKind.ReturnStatement);
|
|
node.expression = expression;
|
|
// return in an ES2018 async generator must be awaited
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsES2018 |
|
|
TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateReturnStatement(node: ReturnStatement, expression: Expression | undefined) {
|
|
return node.expression !== expression
|
|
? update(createReturnStatement(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createWithStatement(expression: Expression, statement: Statement) {
|
|
const node = createBaseNode<WithStatement>(SyntaxKind.WithStatement);
|
|
node.expression = expression;
|
|
node.statement = asEmbeddedStatement(statement);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.statement);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateWithStatement(node: WithStatement, expression: Expression, statement: Statement) {
|
|
return node.expression !== expression
|
|
|| node.statement !== statement
|
|
? update(createWithStatement(expression, statement), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createSwitchStatement(expression: Expression, caseBlock: CaseBlock): SwitchStatement {
|
|
const node = createBaseNode<SwitchStatement>(SyntaxKind.SwitchStatement);
|
|
node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
|
|
node.caseBlock = caseBlock;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.caseBlock);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateSwitchStatement(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) {
|
|
return node.expression !== expression
|
|
|| node.caseBlock !== caseBlock
|
|
? update(createSwitchStatement(expression, caseBlock), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createLabeledStatement(label: string | Identifier, statement: Statement) {
|
|
const node = createBaseNode<LabeledStatement>(SyntaxKind.LabeledStatement);
|
|
node.label = asName(label);
|
|
node.statement = asEmbeddedStatement(statement);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.label) |
|
|
propagateChildFlags(node.statement);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement) {
|
|
return node.label !== label
|
|
|| node.statement !== statement
|
|
? update(createLabeledStatement(label, statement), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createThrowStatement(expression: Expression) {
|
|
const node = createBaseNode<ThrowStatement>(SyntaxKind.ThrowStatement);
|
|
node.expression = expression;
|
|
node.transformFlags |= propagateChildFlags(node.expression);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateThrowStatement(node: ThrowStatement, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createThrowStatement(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) {
|
|
const node = createBaseNode<TryStatement>(SyntaxKind.TryStatement);
|
|
node.tryBlock = tryBlock;
|
|
node.catchClause = catchClause;
|
|
node.finallyBlock = finallyBlock;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.tryBlock) |
|
|
propagateChildFlags(node.catchClause) |
|
|
propagateChildFlags(node.finallyBlock);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) {
|
|
return node.tryBlock !== tryBlock
|
|
|| node.catchClause !== catchClause
|
|
|| node.finallyBlock !== finallyBlock
|
|
? update(createTryStatement(tryBlock, catchClause, finallyBlock), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createDebuggerStatement() {
|
|
return createBaseNode<DebuggerStatement>(SyntaxKind.DebuggerStatement);
|
|
}
|
|
|
|
// @api
|
|
function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) {
|
|
const node = createBaseVariableLikeDeclaration<VariableDeclaration>(
|
|
SyntaxKind.VariableDeclaration,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
name,
|
|
type,
|
|
initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer)
|
|
);
|
|
node.exclamationToken = exclamationToken;
|
|
node.transformFlags |= propagateChildFlags(node.exclamationToken);
|
|
if (exclamationToken) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) {
|
|
return node.name !== name
|
|
|| node.type !== type
|
|
|| node.exclamationToken !== exclamationToken
|
|
|| node.initializer !== initializer
|
|
? update(createVariableDeclaration(name, exclamationToken, type, initializer), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags = NodeFlags.None) {
|
|
const node = createBaseNode<VariableDeclarationList>(SyntaxKind.VariableDeclarationList);
|
|
node.flags |= flags & NodeFlags.BlockScoped;
|
|
node.declarations = createNodeArray(declarations);
|
|
node.transformFlags |=
|
|
propagateChildrenFlags(node.declarations) |
|
|
TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
|
if (flags & NodeFlags.BlockScoped) {
|
|
node.transformFlags |=
|
|
TransformFlags.ContainsES2015 |
|
|
TransformFlags.ContainsBlockScopedBinding;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) {
|
|
return node.declarations !== declarations
|
|
? update(createVariableDeclarationList(declarations, node.flags), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createFunctionDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
asteriskToken: AsteriskToken | undefined,
|
|
name: string | Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
body: Block | undefined
|
|
) {
|
|
const node = createBaseFunctionLikeDeclaration<FunctionDeclaration>(
|
|
SyntaxKind.FunctionDeclaration,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
parameters,
|
|
type,
|
|
body
|
|
);
|
|
node.asteriskToken = asteriskToken;
|
|
if (!node.body || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
}
|
|
else {
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.asteriskToken) |
|
|
TransformFlags.ContainsHoistedDeclarationOrCompletion;
|
|
if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
|
|
if (node.asteriskToken) {
|
|
node.transformFlags |= TransformFlags.ContainsES2018;
|
|
}
|
|
else {
|
|
node.transformFlags |= TransformFlags.ContainsES2017;
|
|
}
|
|
}
|
|
else if (node.asteriskToken) {
|
|
node.transformFlags |= TransformFlags.ContainsGenerator;
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateFunctionDeclaration(
|
|
node: FunctionDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
asteriskToken: AsteriskToken | undefined,
|
|
name: Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
parameters: readonly ParameterDeclaration[],
|
|
type: TypeNode | undefined,
|
|
body: Block | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.asteriskToken !== asteriskToken
|
|
|| node.name !== name
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
|| node.body !== body
|
|
? updateBaseFunctionLikeDeclaration(createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createClassDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
heritageClauses: readonly HeritageClause[] | undefined,
|
|
members: readonly ClassElement[]
|
|
) {
|
|
const node = createBaseClassLikeDeclaration<ClassDeclaration>(
|
|
SyntaxKind.ClassDeclaration,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
heritageClauses,
|
|
members
|
|
);
|
|
if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
}
|
|
else {
|
|
node.transformFlags |= TransformFlags.ContainsES2015;
|
|
if (node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateClassDeclaration(
|
|
node: ClassDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier | undefined,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
heritageClauses: readonly HeritageClause[] | undefined,
|
|
members: readonly ClassElement[]
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.heritageClauses !== heritageClauses
|
|
|| node.members !== members
|
|
? update(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createInterfaceDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | Identifier,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
heritageClauses: readonly HeritageClause[] | undefined,
|
|
members: readonly TypeElement[]
|
|
) {
|
|
const node = createBaseInterfaceOrClassLikeDeclaration<InterfaceDeclaration>(
|
|
SyntaxKind.InterfaceDeclaration,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters,
|
|
heritageClauses
|
|
);
|
|
node.members = createNodeArray(members);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateInterfaceDeclaration(
|
|
node: InterfaceDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
heritageClauses: readonly HeritageClause[] | undefined,
|
|
members: readonly TypeElement[]
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.heritageClauses !== heritageClauses
|
|
|| node.members !== members
|
|
? update(createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createTypeAliasDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | Identifier,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
type: TypeNode
|
|
) {
|
|
const node = createBaseGenericNamedDeclaration<TypeAliasDeclaration>(
|
|
SyntaxKind.TypeAliasDeclaration,
|
|
decorators,
|
|
modifiers,
|
|
name,
|
|
typeParameters
|
|
);
|
|
node.type = type;
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateTypeAliasDeclaration(
|
|
node: TypeAliasDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier,
|
|
typeParameters: readonly TypeParameterDeclaration[] | undefined,
|
|
type: TypeNode
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.type !== type
|
|
? update(createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createEnumDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | Identifier,
|
|
members: readonly EnumMember[]
|
|
) {
|
|
const node = createBaseNamedDeclaration<EnumDeclaration>(
|
|
SyntaxKind.EnumDeclaration,
|
|
decorators,
|
|
modifiers,
|
|
name
|
|
);
|
|
node.members = createNodeArray(members);
|
|
node.transformFlags |=
|
|
propagateChildrenFlags(node.members) |
|
|
TransformFlags.ContainsTypeScript;
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await`
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateEnumDeclaration(
|
|
node: EnumDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier,
|
|
members: readonly EnumMember[]) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.members !== members
|
|
? update(createEnumDeclaration(decorators, modifiers, name, members), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createModuleDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: ModuleName,
|
|
body: ModuleBody | undefined,
|
|
flags = NodeFlags.None
|
|
) {
|
|
const node = createBaseDeclaration<ModuleDeclaration>(
|
|
SyntaxKind.ModuleDeclaration,
|
|
decorators,
|
|
modifiers
|
|
);
|
|
node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation);
|
|
node.name = name;
|
|
node.body = body;
|
|
if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
}
|
|
else {
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.name) |
|
|
propagateChildFlags(node.body) |
|
|
TransformFlags.ContainsTypeScript;
|
|
}
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`.
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateModuleDeclaration(
|
|
node: ModuleDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: ModuleName,
|
|
body: ModuleBody | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.body !== body
|
|
? update(createModuleDeclaration(decorators, modifiers, name, body, node.flags), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createModuleBlock(statements: readonly Statement[]) {
|
|
const node = createBaseNode<ModuleBlock>(SyntaxKind.ModuleBlock);
|
|
node.statements = createNodeArray(statements);
|
|
node.transformFlags |= propagateChildrenFlags(node.statements);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]) {
|
|
return node.statements !== statements
|
|
? update(createModuleBlock(statements), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock {
|
|
const node = createBaseNode<CaseBlock>(SyntaxKind.CaseBlock);
|
|
node.clauses = createNodeArray(clauses);
|
|
node.transformFlags |= propagateChildrenFlags(node.clauses);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) {
|
|
return node.clauses !== clauses
|
|
? update(createCaseBlock(clauses), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNamespaceExportDeclaration(name: string | Identifier) {
|
|
const node = createBaseNamedDeclaration<NamespaceExportDeclaration>(
|
|
SyntaxKind.NamespaceExportDeclaration,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
name
|
|
);
|
|
node.transformFlags = TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier) {
|
|
return node.name !== name
|
|
? update(createNamespaceExportDeclaration(name), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createImportEqualsDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: string | Identifier,
|
|
moduleReference: ModuleReference
|
|
) {
|
|
const node = createBaseNamedDeclaration<ImportEqualsDeclaration>(
|
|
SyntaxKind.ImportEqualsDeclaration,
|
|
decorators,
|
|
modifiers,
|
|
name
|
|
);
|
|
node.moduleReference = moduleReference;
|
|
node.transformFlags |= propagateChildFlags(node.moduleReference);
|
|
if (!isExternalModuleReference(node.moduleReference)) node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateImportEqualsDeclaration(
|
|
node: ImportEqualsDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
name: Identifier,
|
|
moduleReference: ModuleReference
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.name !== name
|
|
|| node.moduleReference !== moduleReference
|
|
? update(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createImportDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
importClause: ImportClause | undefined,
|
|
moduleSpecifier: Expression
|
|
): ImportDeclaration {
|
|
const node = createBaseDeclaration<ImportDeclaration>(
|
|
SyntaxKind.ImportDeclaration,
|
|
decorators,
|
|
modifiers
|
|
);
|
|
node.importClause = importClause;
|
|
node.moduleSpecifier = moduleSpecifier;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.importClause) |
|
|
propagateChildFlags(node.moduleSpecifier);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateImportDeclaration(
|
|
node: ImportDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
importClause: ImportClause | undefined,
|
|
moduleSpecifier: Expression
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.importClause !== importClause
|
|
|| node.moduleSpecifier !== moduleSpecifier
|
|
? update(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause {
|
|
const node = createBaseNode<ImportClause>(SyntaxKind.ImportClause);
|
|
node.isTypeOnly = isTypeOnly;
|
|
node.name = name;
|
|
node.namedBindings = namedBindings;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.name) |
|
|
propagateChildFlags(node.namedBindings);
|
|
if (isTypeOnly) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) {
|
|
return node.isTypeOnly !== isTypeOnly
|
|
|| node.name !== name
|
|
|| node.namedBindings !== namedBindings
|
|
? update(createImportClause(isTypeOnly, name, namedBindings), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNamespaceImport(name: Identifier): NamespaceImport {
|
|
const node = createBaseNode<NamespaceImport>(SyntaxKind.NamespaceImport);
|
|
node.name = name;
|
|
node.transformFlags |= propagateChildFlags(node.name);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNamespaceImport(node: NamespaceImport, name: Identifier) {
|
|
return node.name !== name
|
|
? update(createNamespaceImport(name), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNamespaceExport(name: Identifier): NamespaceExport {
|
|
const node = createBaseNode<NamespaceExport>(SyntaxKind.NamespaceExport);
|
|
node.name = name;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.name) |
|
|
TransformFlags.ContainsESNext;
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNamespaceExport(node: NamespaceExport, name: Identifier) {
|
|
return node.name !== name
|
|
? update(createNamespaceExport(name), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports {
|
|
const node = createBaseNode<NamedImports>(SyntaxKind.NamedImports);
|
|
node.elements = createNodeArray(elements);
|
|
node.transformFlags |= propagateChildrenFlags(node.elements);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]) {
|
|
return node.elements !== elements
|
|
? update(createNamedImports(elements), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier) {
|
|
const node = createBaseNode<ImportSpecifier>(SyntaxKind.ImportSpecifier);
|
|
node.propertyName = propertyName;
|
|
node.name = name;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.propertyName) |
|
|
propagateChildFlags(node.name);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier) {
|
|
return node.propertyName !== propertyName
|
|
|| node.name !== name
|
|
? update(createImportSpecifier(propertyName, name), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createExportAssignment(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
isExportEquals: boolean | undefined,
|
|
expression: Expression
|
|
) {
|
|
const node = createBaseDeclaration<ExportAssignment>(
|
|
SyntaxKind.ExportAssignment,
|
|
decorators,
|
|
modifiers
|
|
);
|
|
node.isExportEquals = isExportEquals;
|
|
node.expression = isExportEquals
|
|
? parenthesizerRules().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression)
|
|
: parenthesizerRules().parenthesizeExpressionOfExportDefault(expression);
|
|
node.transformFlags |= propagateChildFlags(node.expression);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateExportAssignment(
|
|
node: ExportAssignment,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
expression: Expression
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.expression !== expression
|
|
? update(createExportAssignment(decorators, modifiers, node.isExportEquals, expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createExportDeclaration(
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
isTypeOnly: boolean,
|
|
exportClause: NamedExportBindings | undefined,
|
|
moduleSpecifier?: Expression
|
|
) {
|
|
const node = createBaseDeclaration<ExportDeclaration>(
|
|
SyntaxKind.ExportDeclaration,
|
|
decorators,
|
|
modifiers
|
|
);
|
|
node.isTypeOnly = isTypeOnly;
|
|
node.exportClause = exportClause;
|
|
node.moduleSpecifier = moduleSpecifier;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.exportClause) |
|
|
propagateChildFlags(node.moduleSpecifier);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateExportDeclaration(
|
|
node: ExportDeclaration,
|
|
decorators: readonly Decorator[] | undefined,
|
|
modifiers: readonly Modifier[] | undefined,
|
|
isTypeOnly: boolean,
|
|
exportClause: NamedExportBindings | undefined,
|
|
moduleSpecifier: Expression | undefined
|
|
) {
|
|
return node.decorators !== decorators
|
|
|| node.modifiers !== modifiers
|
|
|| node.isTypeOnly !== isTypeOnly
|
|
|| node.exportClause !== exportClause
|
|
|| node.moduleSpecifier !== moduleSpecifier
|
|
? update(createExportDeclaration(decorators, modifiers, isTypeOnly, exportClause, moduleSpecifier), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createNamedExports(elements: readonly ExportSpecifier[]) {
|
|
const node = createBaseNode<NamedExports>(SyntaxKind.NamedExports);
|
|
node.elements = createNodeArray(elements);
|
|
node.transformFlags |= propagateChildrenFlags(node.elements);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]) {
|
|
return node.elements !== elements
|
|
? update(createNamedExports(elements), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier) {
|
|
const node = createBaseNode<ExportSpecifier>(SyntaxKind.ExportSpecifier);
|
|
node.propertyName = asName(propertyName);
|
|
node.name = asName(name);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.propertyName) |
|
|
propagateChildFlags(node.name);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier) {
|
|
return node.propertyName !== propertyName
|
|
|| node.name !== name
|
|
? update(createExportSpecifier(propertyName, name), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createMissingDeclaration() {
|
|
const node = createBaseDeclaration<MissingDeclaration>(
|
|
SyntaxKind.MissingDeclaration,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined
|
|
);
|
|
return node;
|
|
}
|
|
|
|
//
|
|
// Module references
|
|
//
|
|
|
|
// @api
|
|
function createExternalModuleReference(expression: Expression) {
|
|
const node = createBaseNode<ExternalModuleReference>(SyntaxKind.ExternalModuleReference);
|
|
node.expression = expression;
|
|
node.transformFlags |= propagateChildFlags(node.expression);
|
|
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createExternalModuleReference(expression), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// JSDoc
|
|
//
|
|
|
|
// @api
|
|
// createJSDocAllType
|
|
// createJSDocUnknownType
|
|
function createJSDocPrimaryTypeWorker<T extends JSDocType>(kind: T["kind"]) {
|
|
return createBaseNode(kind);
|
|
}
|
|
|
|
// @api
|
|
// createJSDocNonNullableType
|
|
// createJSDocNullableType
|
|
// createJSDocOptionalType
|
|
// createJSDocVariadicType
|
|
// createJSDocNamepathType
|
|
|
|
function createJSDocUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"], type: T["type"]): T {
|
|
const node = createBaseNode<T>(kind);
|
|
node.type = type;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
// updateJSDocNonNullableType
|
|
// updateJSDocNullableType
|
|
// updateJSDocOptionalType
|
|
// updateJSDocVariadicType
|
|
// updateJSDocNamepathType
|
|
function updateJSDocUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"], node: T, type: T["type"]): T {
|
|
return node.type !== type
|
|
? update(createJSDocUnaryTypeWorker(kind, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType {
|
|
const node = createBaseSignatureDeclaration<JSDocFunctionType>(
|
|
SyntaxKind.JSDocFunctionType,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
/*name*/ undefined,
|
|
/*typeParameters*/ undefined,
|
|
parameters,
|
|
type
|
|
);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocFunctionType(node: JSDocFunctionType, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType {
|
|
return node.parameters !== parameters
|
|
|| node.type !== type
|
|
? update(createJSDocFunctionType(parameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType = false): JSDocTypeLiteral {
|
|
const node = createBaseNode<JSDocTypeLiteral>(SyntaxKind.JSDocTypeLiteral);
|
|
node.jsDocPropertyTags = asNodeArray(propertyTags);
|
|
node.isArrayType = isArrayType;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocTypeLiteral(node: JSDocTypeLiteral, propertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean): JSDocTypeLiteral {
|
|
return node.jsDocPropertyTags !== propertyTags
|
|
|| node.isArrayType !== isArrayType
|
|
? update(createJSDocTypeLiteral(propertyTags, isArrayType), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression {
|
|
const node = createBaseNode<JSDocTypeExpression>(SyntaxKind.JSDocTypeExpression);
|
|
node.type = type;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocTypeExpression(node: JSDocTypeExpression, type: TypeNode): JSDocTypeExpression {
|
|
return node.type !== type
|
|
? update(createJSDocTypeExpression(type), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature {
|
|
const node = createBaseNode<JSDocSignature>(SyntaxKind.JSDocSignature);
|
|
node.typeParameters = asNodeArray(typeParameters);
|
|
node.parameters = createNodeArray(parameters);
|
|
node.type = type;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocSignature(node: JSDocSignature, typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type: JSDocReturnTag | undefined): JSDocSignature {
|
|
return node.typeParameters !== typeParameters
|
|
|| node.parameters !== parameters
|
|
|| node.type !== type
|
|
? update(createJSDocSignature(typeParameters, parameters, type), node)
|
|
: node;
|
|
}
|
|
|
|
function getDefaultTagName(node: JSDocTag) {
|
|
const defaultTagName = getDefaultTagNameForKind(node.kind);
|
|
return node.tagName.escapedText === escapeLeadingUnderscores(defaultTagName)
|
|
? node.tagName
|
|
: createIdentifier(defaultTagName);
|
|
}
|
|
|
|
// @api
|
|
function createBaseJSDocTag<T extends JSDocTag>(kind: T["kind"], tagName: Identifier, comment: string | undefined) {
|
|
const node = createBaseNode<T>(kind);
|
|
node.tagName = tagName;
|
|
node.comment = comment;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string): JSDocTemplateTag {
|
|
const node = createBaseJSDocTag<JSDocTemplateTag>(SyntaxKind.JSDocTemplateTag, tagName ?? createIdentifier("template"), comment);
|
|
node.constraint = constraint;
|
|
node.typeParameters = createNodeArray(typeParameters);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocTemplateTag(node: JSDocTemplateTag, tagName: Identifier = getDefaultTagName(node), constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment: string | undefined): JSDocTemplateTag {
|
|
return node.tagName !== tagName
|
|
|| node.constraint !== constraint
|
|
|| node.typeParameters !== typeParameters
|
|
|| node.comment !== comment
|
|
? update(createJSDocTemplateTag(tagName, constraint, typeParameters, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocTypedefTag {
|
|
const node = createBaseJSDocTag<JSDocTypedefTag>(SyntaxKind.JSDocTypedefTag, tagName ?? createIdentifier("typedef"), comment);
|
|
node.typeExpression = typeExpression;
|
|
node.fullName = fullName;
|
|
node.name = getJSDocTypeAliasName(fullName);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocTypedefTag(node: JSDocTypedefTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression | undefined, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | undefined): JSDocTypedefTag {
|
|
return node.tagName !== tagName
|
|
|| node.typeExpression !== typeExpression
|
|
|| node.fullName !== fullName
|
|
|| node.comment !== comment
|
|
? update(createJSDocTypedefTag(tagName, typeExpression, fullName, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocParameterTag {
|
|
const node = createBaseJSDocTag<JSDocParameterTag>(SyntaxKind.JSDocParameterTag, tagName ?? createIdentifier("param"), comment);
|
|
node.typeExpression = typeExpression;
|
|
node.name = name;
|
|
node.isNameFirst = !!isNameFirst;
|
|
node.isBracketed = isBracketed;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocParameterTag(node: JSDocParameterTag, tagName: Identifier = getDefaultTagName(node), name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | undefined): JSDocParameterTag {
|
|
return node.tagName !== tagName
|
|
|| node.name !== name
|
|
|| node.isBracketed !== isBracketed
|
|
|| node.typeExpression !== typeExpression
|
|
|| node.isNameFirst !== isNameFirst
|
|
|| node.comment !== comment
|
|
? update(createJSDocParameterTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string): JSDocPropertyTag {
|
|
const node = createBaseJSDocTag<JSDocPropertyTag>(SyntaxKind.JSDocPropertyTag, tagName ?? createIdentifier("prop"), comment);
|
|
node.typeExpression = typeExpression;
|
|
node.name = name;
|
|
node.isNameFirst = !!isNameFirst;
|
|
node.isBracketed = isBracketed;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier = getDefaultTagName(node), name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | undefined): JSDocPropertyTag {
|
|
return node.tagName !== tagName
|
|
|| node.name !== name
|
|
|| node.isBracketed !== isBracketed
|
|
|| node.typeExpression !== typeExpression
|
|
|| node.isNameFirst !== isNameFirst
|
|
|| node.comment !== comment
|
|
? update(createJSDocPropertyTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocCallbackTag {
|
|
const node = createBaseJSDocTag<JSDocCallbackTag>(SyntaxKind.JSDocCallbackTag, tagName ?? createIdentifier("callback"), comment);
|
|
node.typeExpression = typeExpression;
|
|
node.fullName = fullName;
|
|
node.name = getJSDocTypeAliasName(fullName);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | undefined): JSDocCallbackTag {
|
|
return node.tagName !== tagName
|
|
|| node.typeExpression !== typeExpression
|
|
|| node.fullName !== fullName
|
|
|| node.comment !== comment
|
|
? update(createJSDocCallbackTag(tagName, typeExpression, fullName, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string): JSDocAugmentsTag {
|
|
const node = createBaseJSDocTag<JSDocAugmentsTag>(SyntaxKind.JSDocAugmentsTag, tagName ?? createIdentifier("augments"), comment);
|
|
node.class = className;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocAugmentsTag["class"], comment: string | undefined): JSDocAugmentsTag {
|
|
return node.tagName !== tagName
|
|
|| node.class !== className
|
|
|| node.comment !== comment
|
|
? update(createJSDocAugmentsTag(tagName, className, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string): JSDocImplementsTag {
|
|
const node = createBaseJSDocTag<JSDocImplementsTag>(SyntaxKind.JSDocImplementsTag, tagName ?? createIdentifier("implements"), comment);
|
|
node.class = className;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocImplementsTag["class"], comment: string | undefined): JSDocImplementsTag {
|
|
return node.tagName !== tagName
|
|
|| node.class !== className
|
|
|| node.comment !== comment
|
|
? update(createJSDocImplementsTag(tagName, className, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
// createJSDocAuthorTag
|
|
// createJSDocClassTag
|
|
// createJSDocPublicTag
|
|
// createJSDocPrivateTag
|
|
// createJSDocProtectedTag
|
|
// createJSDocReadonlyTag
|
|
// createJSDocDeprecatedTag
|
|
function createJSDocSimpleTagWorker<T extends JSDocTag>(kind: T["kind"], tagName: Identifier | undefined, comment?: string) {
|
|
const node = createBaseJSDocTag<T>(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
// updateJSDocAuthorTag
|
|
// updateJSDocClassTag
|
|
// updateJSDocPublicTag
|
|
// updateJSDocPrivateTag
|
|
// updateJSDocProtectedTag
|
|
// updateJSDocReadonlyTag
|
|
// updateJSDocDeprecatedTag
|
|
function updateJSDocSimpleTagWorker<T extends JSDocTag>(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), comment: string | undefined) {
|
|
return node.tagName !== tagName
|
|
|| node.comment !== comment
|
|
? update(createJSDocSimpleTagWorker(kind, tagName, comment), node) :
|
|
node;
|
|
}
|
|
|
|
// @api
|
|
// createJSDocTypeTag
|
|
// createJSDocReturnTag
|
|
// createJSDocThisTag
|
|
// createJSDocEnumTag
|
|
function createJSDocTypeLikeTagWorker<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"], tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string) {
|
|
const node = createBaseJSDocTag<T>(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment);
|
|
node.typeExpression = typeExpression;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
// updateJSDocTypeTag
|
|
// updateJSDocReturnTag
|
|
// updateJSDocThisTag
|
|
// updateJSDocEnumTag
|
|
function updateJSDocTypeLikeTagWorker<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression | undefined, comment: string | undefined) {
|
|
return node.tagName !== tagName
|
|
|| node.typeExpression !== typeExpression
|
|
|| node.comment !== comment
|
|
? update(createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocUnknownTag(tagName: Identifier, comment?: string): JSDocUnknownTag {
|
|
const node = createBaseJSDocTag<JSDocUnknownTag>(SyntaxKind.JSDocTag, tagName, comment);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | undefined): JSDocUnknownTag {
|
|
return node.tagName !== tagName
|
|
|| node.comment !== comment
|
|
? update(createJSDocUnknownTag(tagName, comment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJSDocComment(comment?: string | undefined, tags?: readonly JSDocTag[] | undefined) {
|
|
const node = createBaseNode<JSDoc>(SyntaxKind.JSDocComment);
|
|
node.comment = comment;
|
|
node.tags = asNodeArray(tags);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJSDocComment(node: JSDoc, comment: string | undefined, tags: readonly JSDocTag[] | undefined) {
|
|
return node.comment !== comment
|
|
|| node.tags !== tags
|
|
? update(createJSDocComment(comment, tags), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// JSX
|
|
//
|
|
|
|
// @api
|
|
function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) {
|
|
const node = createBaseNode<JsxElement>(SyntaxKind.JsxElement);
|
|
node.openingElement = openingElement;
|
|
node.children = createNodeArray(children);
|
|
node.closingElement = closingElement;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.openingElement) |
|
|
propagateChildrenFlags(node.children) |
|
|
propagateChildFlags(node.closingElement) |
|
|
TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) {
|
|
return node.openingElement !== openingElement
|
|
|| node.children !== children
|
|
|| node.closingElement !== closingElement
|
|
? update(createJsxElement(openingElement, children, closingElement), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) {
|
|
const node = createBaseNode<JsxSelfClosingElement>(SyntaxKind.JsxSelfClosingElement);
|
|
node.tagName = tagName;
|
|
node.typeArguments = asNodeArray(typeArguments);
|
|
node.attributes = attributes;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.tagName) |
|
|
propagateChildrenFlags(node.typeArguments) |
|
|
propagateChildFlags(node.attributes) |
|
|
TransformFlags.ContainsJsx;
|
|
if (node.typeArguments) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) {
|
|
return node.tagName !== tagName
|
|
|| node.typeArguments !== typeArguments
|
|
|| node.attributes !== attributes
|
|
? update(createJsxSelfClosingElement(tagName, typeArguments, attributes), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) {
|
|
const node = createBaseNode<JsxOpeningElement>(SyntaxKind.JsxOpeningElement);
|
|
node.tagName = tagName;
|
|
node.typeArguments = asNodeArray(typeArguments);
|
|
node.attributes = attributes;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.tagName) |
|
|
propagateChildrenFlags(node.typeArguments) |
|
|
propagateChildFlags(node.attributes) |
|
|
TransformFlags.ContainsJsx;
|
|
if (typeArguments) {
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) {
|
|
return node.tagName !== tagName
|
|
|| node.typeArguments !== typeArguments
|
|
|| node.attributes !== attributes
|
|
? update(createJsxOpeningElement(tagName, typeArguments, attributes), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxClosingElement(tagName: JsxTagNameExpression) {
|
|
const node = createBaseNode<JsxClosingElement>(SyntaxKind.JsxClosingElement);
|
|
node.tagName = tagName;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.tagName) |
|
|
TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) {
|
|
return node.tagName !== tagName
|
|
? update(createJsxClosingElement(tagName), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) {
|
|
const node = createBaseNode<JsxFragment>(SyntaxKind.JsxFragment);
|
|
node.openingFragment = openingFragment;
|
|
node.children = createNodeArray(children);
|
|
node.closingFragment = closingFragment;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.openingFragment) |
|
|
propagateChildrenFlags(node.children) |
|
|
propagateChildFlags(node.closingFragment) |
|
|
TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) {
|
|
return node.openingFragment !== openingFragment
|
|
|| node.children !== children
|
|
|| node.closingFragment !== closingFragment
|
|
? update(createJsxFragment(openingFragment, children, closingFragment), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) {
|
|
const node = createBaseNode<JsxText>(SyntaxKind.JsxText);
|
|
node.text = text;
|
|
node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces;
|
|
node.transformFlags |= TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) {
|
|
return node.text !== text
|
|
|| node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces
|
|
? update(createJsxText(text, containsOnlyTriviaWhiteSpaces), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxOpeningFragment() {
|
|
const node = createBaseNode<JsxOpeningFragment>(SyntaxKind.JsxOpeningFragment);
|
|
node.transformFlags |= TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxJsxClosingFragment() {
|
|
const node = createBaseNode<JsxClosingFragment>(SyntaxKind.JsxClosingFragment);
|
|
node.transformFlags |= TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression | undefined) {
|
|
const node = createBaseNode<JsxAttribute>(SyntaxKind.JsxAttribute);
|
|
node.name = name;
|
|
node.initializer = initializer;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.name) |
|
|
propagateChildFlags(node.initializer) |
|
|
TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression | undefined) {
|
|
return node.name !== name
|
|
|| node.initializer !== initializer
|
|
? update(createJsxAttribute(name, initializer), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxAttributes(properties: readonly JsxAttributeLike[]) {
|
|
const node = createBaseNode<JsxAttributes>(SyntaxKind.JsxAttributes);
|
|
node.properties = createNodeArray(properties);
|
|
node.transformFlags |=
|
|
propagateChildrenFlags(node.properties) |
|
|
TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]) {
|
|
return node.properties !== properties
|
|
? update(createJsxAttributes(properties), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxSpreadAttribute(expression: Expression) {
|
|
const node = createBaseNode<JsxSpreadAttribute>(SyntaxKind.JsxSpreadAttribute);
|
|
node.expression = expression;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createJsxSpreadAttribute(expression), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) {
|
|
const node = createBaseNode<JsxExpression>(SyntaxKind.JsxExpression);
|
|
node.dotDotDotToken = dotDotDotToken;
|
|
node.expression = expression;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.dotDotDotToken) |
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsJsx;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) {
|
|
return node.expression !== expression
|
|
? update(createJsxExpression(node.dotDotDotToken, expression), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Clauses
|
|
//
|
|
|
|
// @api
|
|
function createCaseClause(expression: Expression, statements: readonly Statement[]) {
|
|
const node = createBaseNode<CaseClause>(SyntaxKind.CaseClause);
|
|
node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
|
|
node.statements = createNodeArray(statements);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildrenFlags(node.statements);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]) {
|
|
return node.expression !== expression
|
|
|| node.statements !== statements
|
|
? update(createCaseClause(expression, statements), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createDefaultClause(statements: readonly Statement[]) {
|
|
const node = createBaseNode<DefaultClause>(SyntaxKind.DefaultClause);
|
|
node.statements = createNodeArray(statements);
|
|
node.transformFlags = propagateChildrenFlags(node.statements);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]) {
|
|
return node.statements !== statements
|
|
? update(createDefaultClause(statements), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]) {
|
|
const node = createBaseNode<HeritageClause>(SyntaxKind.HeritageClause);
|
|
node.token = token;
|
|
node.types = createNodeArray(types);
|
|
node.transformFlags |= propagateChildrenFlags(node.types);
|
|
switch (token) {
|
|
case SyntaxKind.ExtendsKeyword:
|
|
node.transformFlags |= TransformFlags.ContainsES2015;
|
|
break;
|
|
case SyntaxKind.ImplementsKeyword:
|
|
node.transformFlags |= TransformFlags.ContainsTypeScript;
|
|
break;
|
|
default:
|
|
return Debug.assertNever(token);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) {
|
|
return node.types !== types
|
|
? update(createHeritageClause(node.token, types), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createCatchClause(variableDeclaration: string | VariableDeclaration | undefined, block: Block) {
|
|
const node = createBaseNode<CatchClause>(SyntaxKind.CatchClause);
|
|
variableDeclaration = !isString(variableDeclaration) ? variableDeclaration : createVariableDeclaration(
|
|
variableDeclaration,
|
|
/*exclamationToken*/ undefined,
|
|
/*type*/ undefined,
|
|
/*initializer*/ undefined
|
|
);
|
|
node.variableDeclaration = variableDeclaration;
|
|
node.block = block;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.variableDeclaration) |
|
|
propagateChildFlags(node.block);
|
|
if (!variableDeclaration) node.transformFlags |= TransformFlags.ContainsES2019;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) {
|
|
return node.variableDeclaration !== variableDeclaration
|
|
|| node.block !== block
|
|
? update(createCatchClause(variableDeclaration, block), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Property assignments
|
|
//
|
|
|
|
// @api
|
|
function createPropertyAssignment(name: string | PropertyName, initializer: Expression) {
|
|
const node = createBaseNamedDeclaration<PropertyAssignment>(
|
|
SyntaxKind.PropertyAssignment,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
name
|
|
);
|
|
node.initializer = parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.name) |
|
|
propagateChildFlags(node.initializer);
|
|
return node;
|
|
}
|
|
|
|
function finishUpdatePropertyAssignment(updated: Mutable<PropertyAssignment>, original: PropertyAssignment) {
|
|
// copy children used only for error reporting
|
|
if (original.decorators) updated.decorators = original.decorators;
|
|
if (original.modifiers) updated.modifiers = original.modifiers;
|
|
if (original.questionToken) updated.questionToken = original.questionToken;
|
|
if (original.exclamationToken) updated.exclamationToken = original.exclamationToken;
|
|
return update(updated, original);
|
|
}
|
|
|
|
// @api
|
|
function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression) {
|
|
return node.name !== name
|
|
|| node.initializer !== initializer
|
|
? finishUpdatePropertyAssignment(createPropertyAssignment(name, initializer), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) {
|
|
const node = createBaseNamedDeclaration<ShorthandPropertyAssignment>(
|
|
SyntaxKind.ShorthandPropertyAssignment,
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
name
|
|
);
|
|
node.objectAssignmentInitializer = objectAssignmentInitializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.objectAssignmentInitializer) |
|
|
TransformFlags.ContainsES2015;
|
|
return node;
|
|
}
|
|
|
|
function finishUpdateShorthandPropertyAssignment(updated: Mutable<ShorthandPropertyAssignment>, original: ShorthandPropertyAssignment) {
|
|
// copy children used only for error reporting
|
|
if (original.decorators) updated.decorators = original.decorators;
|
|
if (original.modifiers) updated.modifiers = original.modifiers;
|
|
if (original.equalsToken) updated.equalsToken = original.equalsToken;
|
|
if (original.questionToken) updated.questionToken = original.questionToken;
|
|
if (original.exclamationToken) updated.exclamationToken = original.exclamationToken;
|
|
return update(updated, original);
|
|
}
|
|
|
|
// @api
|
|
function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) {
|
|
return node.name !== name
|
|
|| node.objectAssignmentInitializer !== objectAssignmentInitializer
|
|
? finishUpdateShorthandPropertyAssignment(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createSpreadAssignment(expression: Expression) {
|
|
const node = createBaseNode<SpreadAssignment>(SyntaxKind.SpreadAssignment);
|
|
node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsES2018 |
|
|
TransformFlags.ContainsObjectRestOrSpread;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createSpreadAssignment(expression), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Enum
|
|
//
|
|
|
|
// @api
|
|
function createEnumMember(name: string | PropertyName, initializer?: Expression) {
|
|
const node = createBaseNode<EnumMember>(SyntaxKind.EnumMember);
|
|
node.name = asName(name);
|
|
node.initializer = initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer);
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.name) |
|
|
propagateChildFlags(node.initializer) |
|
|
TransformFlags.ContainsTypeScript;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) {
|
|
return node.name !== name
|
|
|| node.initializer !== initializer
|
|
? update(createEnumMember(name, initializer), node)
|
|
: node;
|
|
}
|
|
|
|
//
|
|
// Top-level nodes
|
|
//
|
|
|
|
// @api
|
|
function createSourceFile(
|
|
statements: readonly Statement[],
|
|
endOfFileToken: EndOfFileToken,
|
|
flags: NodeFlags
|
|
) {
|
|
const node = baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as Mutable<SourceFile>;
|
|
node.statements = createNodeArray(statements);
|
|
node.endOfFileToken = endOfFileToken;
|
|
node.flags |= flags;
|
|
node.fileName = "";
|
|
node.text = "";
|
|
node.languageVersion = 0;
|
|
node.languageVariant = 0;
|
|
node.scriptKind = 0;
|
|
node.isDeclarationFile = false;
|
|
node.hasNoDefaultLib = false;
|
|
node.transformFlags |=
|
|
propagateChildrenFlags(node.statements) |
|
|
propagateChildFlags(node.endOfFileToken);
|
|
return node;
|
|
}
|
|
|
|
function cloneSourceFileWithChanges(
|
|
source: SourceFile,
|
|
statements: readonly Statement[],
|
|
isDeclarationFile: boolean,
|
|
referencedFiles: readonly FileReference[],
|
|
typeReferences: readonly FileReference[],
|
|
hasNoDefaultLib: boolean,
|
|
libReferences: readonly FileReference[]
|
|
) {
|
|
const node = baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as Mutable<SourceFile>;
|
|
for (const p in source) {
|
|
if (p === "emitNode" || hasProperty(node, p) || !hasProperty(source, p)) continue;
|
|
(node as any)[p] = (source as any)[p];
|
|
}
|
|
node.flags |= source.flags;
|
|
node.statements = createNodeArray(statements);
|
|
node.endOfFileToken = source.endOfFileToken;
|
|
node.isDeclarationFile = isDeclarationFile;
|
|
node.referencedFiles = referencedFiles;
|
|
node.typeReferenceDirectives = typeReferences;
|
|
node.hasNoDefaultLib = hasNoDefaultLib;
|
|
node.libReferenceDirectives = libReferences;
|
|
node.transformFlags =
|
|
propagateChildrenFlags(node.statements) |
|
|
propagateChildFlags(node.endOfFileToken);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateSourceFile(
|
|
node: SourceFile,
|
|
statements: readonly Statement[],
|
|
isDeclarationFile = node.isDeclarationFile,
|
|
referencedFiles = node.referencedFiles,
|
|
typeReferenceDirectives = node.typeReferenceDirectives,
|
|
hasNoDefaultLib = node.hasNoDefaultLib,
|
|
libReferenceDirectives = node.libReferenceDirectives
|
|
) {
|
|
return node.statements !== statements
|
|
|| node.isDeclarationFile !== isDeclarationFile
|
|
|| node.referencedFiles !== referencedFiles
|
|
|| node.typeReferenceDirectives !== typeReferenceDirectives
|
|
|| node.hasNoDefaultLib !== hasNoDefaultLib
|
|
|| node.libReferenceDirectives !== libReferenceDirectives
|
|
? update(cloneSourceFileWithChanges(node, statements, isDeclarationFile, referencedFiles, typeReferenceDirectives, hasNoDefaultLib, libReferenceDirectives), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createBundle(sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) {
|
|
const node = createBaseNode<Bundle>(SyntaxKind.Bundle);
|
|
node.prepends = prepends;
|
|
node.sourceFiles = sourceFiles;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) {
|
|
return node.sourceFiles !== sourceFiles
|
|
|| node.prepends !== prepends
|
|
? update(createBundle(sourceFiles, prepends), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function createUnparsedSource(prologues: readonly UnparsedPrologue[], syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, texts: readonly UnparsedSourceText[]) {
|
|
const node = createBaseNode<UnparsedSource>(SyntaxKind.UnparsedSource);
|
|
node.prologues = prologues;
|
|
node.syntheticReferences = syntheticReferences;
|
|
node.texts = texts;
|
|
node.fileName = "";
|
|
node.text = "";
|
|
node.referencedFiles = emptyArray;
|
|
node.libReferenceDirectives = emptyArray;
|
|
node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos);
|
|
return node;
|
|
}
|
|
|
|
function createBaseUnparsedNode<T extends UnparsedNode>(kind: T["kind"], data?: string) {
|
|
const node = createBaseNode(kind);
|
|
node.data = data;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createUnparsedPrologue(data?: string): UnparsedPrologue {
|
|
return createBaseUnparsedNode(SyntaxKind.UnparsedPrologue, data);
|
|
}
|
|
|
|
// @api
|
|
function createUnparsedPrepend(data: string | undefined, texts: readonly UnparsedTextLike[]): UnparsedPrepend {
|
|
const node = createBaseUnparsedNode<UnparsedPrepend>(SyntaxKind.UnparsedPrepend, data);
|
|
node.texts = texts;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createUnparsedTextLike(data: string | undefined, internal: boolean): UnparsedTextLike {
|
|
return createBaseUnparsedNode(internal ? SyntaxKind.UnparsedInternalText : SyntaxKind.UnparsedText, data);
|
|
}
|
|
|
|
// @api
|
|
function createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference): UnparsedSyntheticReference {
|
|
const node = createBaseNode<UnparsedSyntheticReference>(SyntaxKind.UnparsedSyntheticReference);
|
|
node.data = section.data;
|
|
node.section = section;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createInputFiles(): InputFiles {
|
|
const node = createBaseNode<InputFiles>(SyntaxKind.InputFiles);
|
|
node.javascriptText = "";
|
|
node.declarationText = "";
|
|
return node;
|
|
}
|
|
|
|
//
|
|
// Synthetic Nodes (used by checker)
|
|
//
|
|
|
|
// @api
|
|
function createSyntheticExpression(type: Type, isSpread = false, tupleNameSource?: ParameterDeclaration | NamedTupleMember) {
|
|
const node = createBaseNode<SyntheticExpression>(SyntaxKind.SyntheticExpression);
|
|
node.type = type;
|
|
node.isSpread = isSpread;
|
|
node.tupleNameSource = tupleNameSource;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createSyntaxList(children: Node[]) {
|
|
const node = createBaseNode<SyntaxList>(SyntaxKind.SyntaxList);
|
|
node._children = children;
|
|
return node;
|
|
}
|
|
|
|
//
|
|
// Transformation nodes
|
|
//
|
|
|
|
/**
|
|
* Creates a synthetic statement to act as a placeholder for a not-emitted statement in
|
|
* order to preserve comments.
|
|
*
|
|
* @param original The original statement.
|
|
*/
|
|
// @api
|
|
function createNotEmittedStatement(original: Node) {
|
|
const node = createBaseNode<NotEmittedStatement>(SyntaxKind.NotEmittedStatement);
|
|
node.original = original;
|
|
setTextRange(node, original);
|
|
return node;
|
|
}
|
|
|
|
/**
|
|
* Creates a synthetic expression to act as a placeholder for a not-emitted expression in
|
|
* order to preserve comments or sourcemap positions.
|
|
*
|
|
* @param expression The inner expression to emit.
|
|
* @param original The original outer expression.
|
|
*/
|
|
// @api
|
|
function createPartiallyEmittedExpression(expression: Expression, original?: Node) {
|
|
const node = createBaseNode<PartiallyEmittedExpression>(SyntaxKind.PartiallyEmittedExpression);
|
|
node.expression = expression;
|
|
node.original = original;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
TransformFlags.ContainsTypeScript;
|
|
setTextRange(node, original);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression) {
|
|
return node.expression !== expression
|
|
? update(createPartiallyEmittedExpression(expression, node.original), node)
|
|
: node;
|
|
}
|
|
|
|
function flattenCommaElements(node: Expression): Expression | readonly Expression[] {
|
|
if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) {
|
|
if (isCommaListExpression(node)) {
|
|
return node.elements;
|
|
}
|
|
if (isBinaryExpression(node) && isCommaToken(node.operatorToken)) {
|
|
return [node.left, node.right];
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createCommaListExpression(elements: readonly Expression[]) {
|
|
const node = createBaseNode<CommaListExpression>(SyntaxKind.CommaListExpression);
|
|
node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements));
|
|
node.transformFlags |= propagateChildrenFlags(node.elements);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]) {
|
|
return node.elements !== elements
|
|
? update(createCommaListExpression(elements), node)
|
|
: node;
|
|
}
|
|
|
|
/**
|
|
* Creates a synthetic element to act as a placeholder for the end of an emitted declaration in
|
|
* order to properly emit exports.
|
|
*/
|
|
// @api
|
|
function createEndOfDeclarationMarker(original: Node) {
|
|
const node = createBaseNode<EndOfDeclarationMarker>(SyntaxKind.EndOfDeclarationMarker);
|
|
node.emitNode = {} as EmitNode;
|
|
node.original = original;
|
|
return node;
|
|
}
|
|
|
|
/**
|
|
* Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in
|
|
* order to properly emit exports.
|
|
*/
|
|
// @api
|
|
function createMergeDeclarationMarker(original: Node) {
|
|
const node = createBaseNode<MergeDeclarationMarker>(SyntaxKind.MergeDeclarationMarker);
|
|
node.emitNode = {} as EmitNode;
|
|
node.original = original;
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function createSyntheticReferenceExpression(expression: Expression, thisArg: Expression) {
|
|
const node = createBaseNode<SyntheticReferenceExpression>(SyntaxKind.SyntheticReferenceExpression);
|
|
node.expression = expression;
|
|
node.thisArg = thisArg;
|
|
node.transformFlags |=
|
|
propagateChildFlags(node.expression) |
|
|
propagateChildFlags(node.thisArg);
|
|
return node;
|
|
}
|
|
|
|
// @api
|
|
function updateSyntheticReferenceExpression(node: SyntheticReferenceExpression, expression: Expression, thisArg: Expression) {
|
|
return node.expression !== expression
|
|
|| node.thisArg !== thisArg
|
|
? update(createSyntheticReferenceExpression(expression, thisArg), node)
|
|
: node;
|
|
}
|
|
|
|
// @api
|
|
function cloneNode<T extends Node | undefined>(node: T): T;
|
|
function cloneNode<T extends Node>(node: T) {
|
|
// We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
|
|
// the original node. We also need to exclude specific properties and only include own-
|
|
// properties (to skip members already defined on the shared prototype).
|
|
if (node === undefined) {
|
|
return node;
|
|
}
|
|
|
|
const clone =
|
|
isSourceFile(node) ? baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as T :
|
|
isIdentifier(node) ? baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as T :
|
|
isPrivateIdentifier(node) ? baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as T :
|
|
!isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T :
|
|
baseFactory.createBaseNode(node.kind) as T;
|
|
|
|
(clone as Mutable<T>).flags |= (node.flags & ~NodeFlags.Synthesized);
|
|
(clone as Mutable<T>).transformFlags = node.transformFlags;
|
|
setOriginalNode(clone, node);
|
|
|
|
for (const key in node) {
|
|
if (clone.hasOwnProperty(key) || !node.hasOwnProperty(key)) {
|
|
continue;
|
|
}
|
|
|
|
clone[key] = node[key];
|
|
}
|
|
|
|
return clone;
|
|
}
|
|
|
|
// compound nodes
|
|
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(
|
|
/*modifiers*/ undefined,
|
|
/*asteriskToken*/ undefined,
|
|
/*name*/ undefined,
|
|
/*typeParameters*/ undefined,
|
|
/*parameters*/ param ? [param] : [],
|
|
/*type*/ undefined,
|
|
createBlock(statements, /*multiLine*/ true)
|
|
),
|
|
/*typeArguments*/ undefined,
|
|
/*argumentsArray*/ paramValue ? [paramValue] : []
|
|
);
|
|
}
|
|
|
|
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(
|
|
/*modifiers*/ undefined,
|
|
/*typeParameters*/ undefined,
|
|
/*parameters*/ param ? [param] : [],
|
|
/*type*/ undefined,
|
|
/*equalsGreaterThanToken*/ undefined,
|
|
createBlock(statements, /*multiLine*/ true)
|
|
),
|
|
/*typeArguments*/ undefined,
|
|
/*argumentsArray*/ paramValue ? [paramValue] : []
|
|
);
|
|
}
|
|
|
|
function createVoidZero() {
|
|
return createVoidExpression(createNumericLiteral("0"));
|
|
}
|
|
|
|
function createExportDefault(expression: Expression) {
|
|
return createExportAssignment(
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
/*isExportEquals*/ false,
|
|
expression);
|
|
}
|
|
|
|
function createExternalModuleExport(exportName: Identifier) {
|
|
return createExportDeclaration(
|
|
/*decorators*/ undefined,
|
|
/*modifiers*/ undefined,
|
|
/*isTypeOnly*/ false,
|
|
createNamedExports([
|
|
createExportSpecifier(/*propertyName*/ undefined, exportName)
|
|
])
|
|
);
|
|
}
|
|
|
|
//
|
|
// Utilities
|
|
//
|
|
|
|
function createTypeCheck(value: Expression, tag: TypeOfTag) {
|
|
return tag === "undefined"
|
|
? factory.createStrictEquality(value, createVoidZero())
|
|
: factory.createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag));
|
|
}
|
|
|
|
function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) {
|
|
return createCallExpression(
|
|
createPropertyAccessExpression(object, methodName),
|
|
/*typeArguments*/ undefined,
|
|
argumentsList
|
|
);
|
|
}
|
|
|
|
function createFunctionBindCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]) {
|
|
return createMethodCall(target, "bind", [thisArg, ...argumentsList]);
|
|
}
|
|
|
|
function createFunctionCallCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]) {
|
|
return createMethodCall(target, "call", [thisArg, ...argumentsList]);
|
|
}
|
|
|
|
function createFunctionApplyCall(target: Expression, thisArg: Expression, argumentsExpression: Expression) {
|
|
return createMethodCall(target, "apply", [thisArg, argumentsExpression]);
|
|
}
|
|
|
|
function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly Expression[]) {
|
|
return createMethodCall(createIdentifier(globalObjectName), methodName, argumentsList);
|
|
}
|
|
|
|
function createArraySliceCall(array: Expression, start?: number | Expression) {
|
|
return createMethodCall(array, "slice", start === undefined ? [] : [asExpression(start)]);
|
|
}
|
|
|
|
function createArrayConcatCall(array: Expression, argumentsList: readonly Expression[]) {
|
|
return createMethodCall(array, "concat", argumentsList);
|
|
}
|
|
|
|
function createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression) {
|
|
return createGlobalMethodCall("Object", "defineProperty", [target, asExpression(propertyName), attributes]);
|
|
}
|
|
|
|
function tryAddPropertyAssignment(properties: Push<PropertyAssignment>, propertyName: string, expression: Expression | undefined) {
|
|
if (expression) {
|
|
properties.push(createPropertyAssignment(propertyName, expression));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function createPropertyDescriptor(attributes: PropertyDescriptorAttributes, singleLine?: boolean) {
|
|
const properties: PropertyAssignment[] = [];
|
|
tryAddPropertyAssignment(properties, "enumerable", asExpression(attributes.enumerable));
|
|
tryAddPropertyAssignment(properties, "configurable", asExpression(attributes.configurable));
|
|
|
|
let isData = tryAddPropertyAssignment(properties, "writable", asExpression(attributes.writable));
|
|
isData = tryAddPropertyAssignment(properties, "value", attributes.value) || isData;
|
|
|
|
let isAccessor = tryAddPropertyAssignment(properties, "get", attributes.get);
|
|
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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Determines whether a node is a parenthesized expression that can be ignored when recreating outer expressions.
|
|
*
|
|
* A parenthesized expression can be ignored when all of the following are true:
|
|
*
|
|
* - It's `pos` and `end` are not -1
|
|
* - It does not have a custom source map range
|
|
* - It does not have a custom comment range
|
|
* - It does not have synthetic leading or trailing comments
|
|
*
|
|
* If an outermost parenthesized expression is ignored, but the containing expression requires a parentheses around
|
|
* the expression to maintain precedence, a new parenthesized expression should be created automatically when
|
|
* the containing expression is created/updated.
|
|
*/
|
|
function isIgnorableParen(node: Expression) {
|
|
return isParenthesizedExpression(node)
|
|
&& nodeIsSynthesized(node)
|
|
&& nodeIsSynthesized(getSourceMapRange(node))
|
|
&& nodeIsSynthesized(getCommentRange(node))
|
|
&& !some(getSyntheticLeadingComments(node))
|
|
&& !some(getSyntheticTrailingComments(node));
|
|
}
|
|
|
|
function restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds = OuterExpressionKinds.All): Expression {
|
|
if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) {
|
|
return updateOuterExpression(
|
|
outerExpression,
|
|
restoreOuterExpressions(outerExpression.expression, innerExpression)
|
|
);
|
|
}
|
|
return innerExpression;
|
|
}
|
|
|
|
function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement {
|
|
if (!outermostLabeledStatement) {
|
|
return node;
|
|
}
|
|
const updated = updateLabeledStatement(
|
|
outermostLabeledStatement,
|
|
outermostLabeledStatement.label,
|
|
isLabeledStatement(outermostLabeledStatement.statement)
|
|
? restoreEnclosingLabel(node, outermostLabeledStatement.statement)
|
|
: node
|
|
);
|
|
if (afterRestoreLabelCallback) {
|
|
afterRestoreLabelCallback(outermostLabeledStatement);
|
|
}
|
|
return updated;
|
|
}
|
|
|
|
function shouldBeCapturedInTempVariable(node: Expression, cacheIdentifiers: boolean): boolean {
|
|
const target = skipParentheses(node);
|
|
switch (target.kind) {
|
|
case SyntaxKind.Identifier:
|
|
return cacheIdentifiers;
|
|
case SyntaxKind.ThisKeyword:
|
|
case SyntaxKind.NumericLiteral:
|
|
case SyntaxKind.BigIntLiteral:
|
|
case SyntaxKind.StringLiteral:
|
|
return false;
|
|
case SyntaxKind.ArrayLiteralExpression:
|
|
const elements = (<ArrayLiteralExpression>target).elements;
|
|
if (elements.length === 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
case SyntaxKind.ObjectLiteralExpression:
|
|
return (<ObjectLiteralExpression>target).properties.length > 0;
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers = false): CallBinding {
|
|
const callee = skipOuterExpressions(expression, OuterExpressionKinds.All);
|
|
let thisArg: Expression;
|
|
let target: LeftHandSideExpression;
|
|
if (isSuperProperty(callee)) {
|
|
thisArg = createThis();
|
|
target = callee;
|
|
}
|
|
else if (isSuperKeyword(callee)) {
|
|
thisArg = createThis();
|
|
target = languageVersion !== undefined && languageVersion < ScriptTarget.ES2015
|
|
? setTextRange(createIdentifier("_super"), callee)
|
|
: <PrimaryExpression>callee;
|
|
}
|
|
else if (getEmitFlags(callee) & EmitFlags.HelperName) {
|
|
thisArg = createVoidZero();
|
|
target = parenthesizerRules().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(
|
|
setTextRange(
|
|
factory.createAssignment(
|
|
thisArg,
|
|
callee.expression
|
|
),
|
|
callee.expression
|
|
),
|
|
callee.name
|
|
);
|
|
setTextRange(target, callee);
|
|
}
|
|
else {
|
|
thisArg = callee.expression;
|
|
target = callee;
|
|
}
|
|
}
|
|
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(
|
|
setTextRange(
|
|
factory.createAssignment(
|
|
thisArg,
|
|
callee.expression
|
|
),
|
|
callee.expression
|
|
),
|
|
callee.argumentExpression
|
|
);
|
|
setTextRange(target, callee);
|
|
}
|
|
else {
|
|
thisArg = callee.expression;
|
|
target = callee;
|
|
}
|
|
}
|
|
else {
|
|
// for `a()` target is `a` and thisArg is `void 0`
|
|
thisArg = createVoidZero();
|
|
target = parenthesizerRules().parenthesizeLeftSideOfAccess(expression);
|
|
}
|
|
|
|
return { target, thisArg };
|
|
}
|
|
|
|
function inlineExpressions(expressions: readonly Expression[]) {
|
|
// 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, factory.createComma)!;
|
|
}
|
|
|
|
function getName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) {
|
|
const nodeName = getNameOfDeclaration(node);
|
|
if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) {
|
|
// TODO(rbuckton): Does this need to be parented?
|
|
const name = setParent(setTextRange(cloneNode(nodeName), nodeName), nodeName.parent);
|
|
emitFlags |= getEmitFlags(nodeName);
|
|
if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap;
|
|
if (!allowComments) emitFlags |= EmitFlags.NoComments;
|
|
if (emitFlags) setEmitFlags(name, emitFlags);
|
|
return name;
|
|
}
|
|
return getGeneratedNameForNode(node);
|
|
}
|
|
|
|
/**
|
|
* Gets the internal name of a declaration. This is primarily used for declarations that can be
|
|
* referred to by name in the body of an ES5 class function body. An internal name will *never*
|
|
* be prefixed with an module or namespace export modifier like "exports." when emitted as an
|
|
* expression. An internal name will also *never* be renamed due to a collision with a block
|
|
* scoped variable.
|
|
*
|
|
* @param node The declaration.
|
|
* @param allowComments A value indicating whether comments may be emitted for the name.
|
|
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
|
*/
|
|
function getInternalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) {
|
|
return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName | EmitFlags.InternalName);
|
|
}
|
|
|
|
/**
|
|
* Gets the local name of a declaration. This is primarily used for declarations that can be
|
|
* referred to by name in the declaration's immediate scope (classes, enums, namespaces). A
|
|
* local name will *never* be prefixed with an module or namespace export modifier like
|
|
* "exports." when emitted as an expression.
|
|
*
|
|
* @param node The declaration.
|
|
* @param allowComments A value indicating whether comments may be emitted for the name.
|
|
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
|
*/
|
|
function getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) {
|
|
return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName);
|
|
}
|
|
|
|
/**
|
|
* Gets the export name of a declaration. This is primarily used for declarations that can be
|
|
* referred to by name in the declaration's immediate scope (classes, enums, namespaces). An
|
|
* export name will *always* be prefixed with an module or namespace export modifier like
|
|
* `"exports."` when emitted as an expression if the name points to an exported symbol.
|
|
*
|
|
* @param node The declaration.
|
|
* @param allowComments A value indicating whether comments may be emitted for the name.
|
|
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
|
*/
|
|
function getExportName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier {
|
|
return getName(node, allowComments, allowSourceMaps, EmitFlags.ExportName);
|
|
}
|
|
|
|
/**
|
|
* Gets the name of a declaration for use in declarations.
|
|
*
|
|
* @param node The declaration.
|
|
* @param allowComments A value indicating whether comments may be emitted for the name.
|
|
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
|
*/
|
|
function getDeclarationName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) {
|
|
return getName(node, allowComments, allowSourceMaps);
|
|
}
|
|
|
|
/**
|
|
* Gets a namespace-qualified name for use in expressions.
|
|
*
|
|
* @param ns The namespace identifier.
|
|
* @param name The name.
|
|
* @param allowComments A value indicating whether comments may be emitted for the name.
|
|
* @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 : cloneNode(name));
|
|
setTextRange(qualifiedName, name);
|
|
let emitFlags: EmitFlags = 0;
|
|
if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap;
|
|
if (!allowComments) emitFlags |= EmitFlags.NoComments;
|
|
if (emitFlags) setEmitFlags(qualifiedName, emitFlags);
|
|
return qualifiedName;
|
|
}
|
|
|
|
/**
|
|
* Gets the exported name of a declaration for use in expressions.
|
|
*
|
|
* An exported name will *always* be prefixed with an module or namespace export modifier like
|
|
* "exports." if the name points to an exported symbol.
|
|
*
|
|
* @param ns The namespace identifier.
|
|
* @param node The declaration.
|
|
* @param allowComments A value indicating whether comments may be emitted for the name.
|
|
* @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
|
|
*/
|
|
function getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression {
|
|
if (ns && hasSyntacticModifier(node, ModifierFlags.Export)) {
|
|
return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps);
|
|
}
|
|
return getExportName(node, allowComments, allowSourceMaps);
|
|
}
|
|
|
|
/**
|
|
* Copies any necessary standard and custom prologue-directives into target array.
|
|
* @param source origin statements array
|
|
* @param target result statements array
|
|
* @param ensureUseStrict boolean determining whether the function need to add prologue-directives
|
|
* @param visitor Optional callback used to visit any custom prologue directives.
|
|
*/
|
|
function copyPrologue(source: readonly Statement[], target: Push<Statement>, ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult<Node>): number {
|
|
const offset = copyStandardPrologue(source, target, ensureUseStrict);
|
|
return copyCustomPrologue(source, target, offset, visitor);
|
|
}
|
|
|
|
function isUseStrictPrologue(node: ExpressionStatement): boolean {
|
|
return isStringLiteral(node.expression) && node.expression.text === "use strict";
|
|
}
|
|
|
|
function createUseStrictPrologue() {
|
|
return startOnNewLine(createExpressionStatement(createStringLiteral("use strict"))) as PrologueDirective;
|
|
}
|
|
|
|
/**
|
|
* Copies only the standard (string-expression) prologue-directives into the target statement-array.
|
|
* @param source origin statements array
|
|
* @param target result statements array
|
|
* @param ensureUseStrict boolean determining whether the function need to add prologue-directives
|
|
*/
|
|
function copyStandardPrologue(source: readonly Statement[], target: Push<Statement>, ensureUseStrict?: boolean): number {
|
|
Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array");
|
|
let foundUseStrict = false;
|
|
let statementOffset = 0;
|
|
const numStatements = source.length;
|
|
while (statementOffset < numStatements) {
|
|
const statement = source[statementOffset];
|
|
if (isPrologueDirective(statement)) {
|
|
if (isUseStrictPrologue(statement)) {
|
|
foundUseStrict = true;
|
|
}
|
|
target.push(statement);
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
statementOffset++;
|
|
}
|
|
if (ensureUseStrict && !foundUseStrict) {
|
|
target.push(createUseStrictPrologue());
|
|
}
|
|
return statementOffset;
|
|
}
|
|
|
|
/**
|
|
* Copies only the custom prologue-directives into target statement-array.
|
|
* @param source origin statements array
|
|
* @param target result statements array
|
|
* @param statementOffset The offset at which to begin the copy.
|
|
* @param visitor Optional callback used to visit any custom prologue directives.
|
|
*/
|
|
function copyCustomPrologue(source: readonly Statement[], target: Push<Statement>, statementOffset: number, visitor?: (node: Node) => VisitResult<Node>, filter?: (node: Node) => boolean): number;
|
|
function copyCustomPrologue(source: readonly Statement[], target: Push<Statement>, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult<Node>, filter?: (node: Node) => boolean): number | undefined;
|
|
function copyCustomPrologue(source: readonly Statement[], target: Push<Statement>, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult<Node>, filter: (node: Node) => boolean = returnTrue): number | undefined {
|
|
const numStatements = source.length;
|
|
while (statementOffset !== undefined && statementOffset < numStatements) {
|
|
const statement = source[statementOffset];
|
|
if (getEmitFlags(statement) & EmitFlags.CustomPrologue && filter(statement)) {
|
|
append(target, visitor ? visitNode(statement, visitor, isStatement) : statement);
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
statementOffset++;
|
|
}
|
|
return statementOffset;
|
|
}
|
|
|
|
/**
|
|
* Ensures "use strict" directive is added
|
|
*
|
|
* @param statements An array of statements
|
|
*/
|
|
function ensureUseStrict(statements: NodeArray<Statement>): NodeArray<Statement> {
|
|
const foundUseStrict = findUseStrictPrologue(statements);
|
|
|
|
if (!foundUseStrict) {
|
|
return setTextRange(createNodeArray<Statement>([createUseStrictPrologue(), ...statements]), statements);
|
|
}
|
|
|
|
return statements;
|
|
}
|
|
|
|
/**
|
|
* Lifts a NodeArray containing only Statement nodes to a block.
|
|
*
|
|
* @param nodes The NodeArray.
|
|
*/
|
|
function liftToBlock(nodes: readonly Node[]): Statement {
|
|
Debug.assert(every(nodes, isStatementOrBlock), "Cannot lift nodes to a Block.");
|
|
return <Statement>singleOrUndefined(nodes) || createBlock(<readonly Statement[]>nodes);
|
|
}
|
|
|
|
function findSpanEnd<T>(array: readonly T[], test: (value: T) => boolean, start: number) {
|
|
let i = start;
|
|
while (i < array.length && test(array[i])) {
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: readonly Statement[] | undefined): NodeArray<Statement>;
|
|
function mergeLexicalEnvironment(statements: Statement[], declarations: readonly Statement[] | undefined): Statement[];
|
|
function mergeLexicalEnvironment(statements: Statement[] | NodeArray<Statement>, declarations: readonly Statement[] | undefined) {
|
|
if (!some(declarations)) {
|
|
return statements;
|
|
}
|
|
|
|
// When we merge new lexical statements into an existing statement list, we merge them in the following manner:
|
|
//
|
|
// Given:
|
|
//
|
|
// | Left | Right |
|
|
// |------------------------------------|-------------------------------------|
|
|
// | [standard prologues (left)] | [standard prologues (right)] |
|
|
// | [hoisted functions (left)] | [hoisted functions (right)] |
|
|
// | [hoisted variables (left)] | [hoisted variables (right)] |
|
|
// | [lexical init statements (left)] | [lexical init statements (right)] |
|
|
// | [other statements (left)] | |
|
|
//
|
|
// The resulting statement list will be:
|
|
//
|
|
// | Result |
|
|
// |-------------------------------------|
|
|
// | [standard prologues (right)] |
|
|
// | [standard prologues (left)] |
|
|
// | [hoisted functions (right)] |
|
|
// | [hoisted functions (left)] |
|
|
// | [hoisted variables (right)] |
|
|
// | [hoisted variables (left)] |
|
|
// | [lexical init statements (right)] |
|
|
// | [lexical init statements (left)] |
|
|
// | [other statements (left)] |
|
|
//
|
|
// NOTE: It is expected that new lexical init statements must be evaluated before existing lexical init statements,
|
|
// as the prior transformation may depend on the evaluation of the lexical init statements to be in the correct state.
|
|
|
|
// find standard prologues on left in the following order: standard directives, hoisted functions, hoisted variables, other custom
|
|
const leftStandardPrologueEnd = findSpanEnd(statements, isPrologueDirective, 0);
|
|
const leftHoistedFunctionsEnd = findSpanEnd(statements, isHoistedFunction, leftStandardPrologueEnd);
|
|
const leftHoistedVariablesEnd = findSpanEnd(statements, isHoistedVariableStatement, leftHoistedFunctionsEnd);
|
|
|
|
// find standard prologues on right in the following order: standard directives, hoisted functions, hoisted variables, other custom
|
|
const rightStandardPrologueEnd = findSpanEnd(declarations, isPrologueDirective, 0);
|
|
const rightHoistedFunctionsEnd = findSpanEnd(declarations, isHoistedFunction, rightStandardPrologueEnd);
|
|
const rightHoistedVariablesEnd = findSpanEnd(declarations, isHoistedVariableStatement, rightHoistedFunctionsEnd);
|
|
const rightCustomPrologueEnd = findSpanEnd(declarations, isCustomPrologue, rightHoistedVariablesEnd);
|
|
Debug.assert(rightCustomPrologueEnd === declarations.length, "Expected declarations to be valid standard or custom prologues");
|
|
|
|
// splice prologues from the right into the left. We do this in reverse order
|
|
// so that we don't need to recompute the index on the left when we insert items.
|
|
const left = isNodeArray(statements) ? statements.slice() : statements;
|
|
|
|
// splice other custom prologues from right into left
|
|
if (rightCustomPrologueEnd > rightHoistedVariablesEnd) {
|
|
left.splice(leftHoistedVariablesEnd, 0, ...declarations.slice(rightHoistedVariablesEnd, rightCustomPrologueEnd));
|
|
}
|
|
|
|
// splice hoisted variables from right into left
|
|
if (rightHoistedVariablesEnd > rightHoistedFunctionsEnd) {
|
|
left.splice(leftHoistedFunctionsEnd, 0, ...declarations.slice(rightHoistedFunctionsEnd, rightHoistedVariablesEnd));
|
|
}
|
|
|
|
// splice hoisted functions from right into left
|
|
if (rightHoistedFunctionsEnd > rightStandardPrologueEnd) {
|
|
left.splice(leftStandardPrologueEnd, 0, ...declarations.slice(rightStandardPrologueEnd, rightHoistedFunctionsEnd));
|
|
}
|
|
|
|
// splice standard prologues from right into left (that are not already in left)
|
|
if (rightStandardPrologueEnd > 0) {
|
|
if (leftStandardPrologueEnd === 0) {
|
|
left.splice(0, 0, ...declarations.slice(0, rightStandardPrologueEnd));
|
|
}
|
|
else {
|
|
const leftPrologues = new Map<string, boolean>();
|
|
for (let i = 0; i < leftStandardPrologueEnd; i++) {
|
|
const leftPrologue = statements[i] as PrologueDirective;
|
|
leftPrologues.set(leftPrologue.expression.text, true);
|
|
}
|
|
for (let i = rightStandardPrologueEnd - 1; i >= 0; i--) {
|
|
const rightPrologue = declarations[i] as PrologueDirective;
|
|
if (!leftPrologues.has(rightPrologue.expression.text)) {
|
|
left.unshift(rightPrologue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isNodeArray(statements)) {
|
|
return setTextRange(createNodeArray(left, statements.hasTrailingComma), statements);
|
|
}
|
|
|
|
return statements;
|
|
}
|
|
|
|
function updateModifiers<T extends HasModifiers>(node: T, modifiers: readonly Modifier[] | ModifierFlags): T;
|
|
function updateModifiers(node: HasModifiers, modifiers: readonly Modifier[] | ModifierFlags) {
|
|
if (typeof modifiers === "number") {
|
|
modifiers = createModifiersFromModifierFlags(modifiers);
|
|
}
|
|
return isParameter(node) ? updateParameterDeclaration(node, node.decorators, modifiers, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) :
|
|
isPropertySignature(node) ? updatePropertySignature(node, modifiers, node.name, node.questionToken, node.type) :
|
|
isPropertyDeclaration(node) ? updatePropertyDeclaration(node, node.decorators, modifiers, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) :
|
|
isMethodSignature(node) ? updateMethodSignature(node, modifiers, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) :
|
|
isMethodDeclaration(node) ? updateMethodDeclaration(node, node.decorators, modifiers, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) :
|
|
isConstructorDeclaration(node) ? updateConstructorDeclaration(node, node.decorators, modifiers, node.parameters, node.body) :
|
|
isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.type, node.body) :
|
|
isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, node.decorators, modifiers, node.name, node.parameters, node.body) :
|
|
isIndexSignatureDeclaration(node) ? updateIndexSignature(node, node.decorators, modifiers, node.parameters, node.type) :
|
|
isFunctionExpression(node) ? updateFunctionExpression(node, modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
|
|
isArrowFunction(node) ? updateArrowFunction(node, modifiers, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) :
|
|
isClassExpression(node) ? updateClassExpression(node, node.decorators, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
|
isVariableStatement(node) ? updateVariableStatement(node, modifiers, node.declarationList) :
|
|
isFunctionDeclaration(node) ? updateFunctionDeclaration(node, node.decorators, modifiers, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
|
|
isClassDeclaration(node) ? updateClassDeclaration(node, node.decorators, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
|
isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, node.decorators, modifiers, node.name, node.typeParameters, node.heritageClauses, node.members) :
|
|
isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, node.decorators, modifiers, node.name, node.typeParameters, node.type) :
|
|
isEnumDeclaration(node) ? updateEnumDeclaration(node, node.decorators, modifiers, node.name, node.members) :
|
|
isModuleDeclaration(node) ? updateModuleDeclaration(node, node.decorators, modifiers, node.name, node.body) :
|
|
isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, node.decorators, modifiers, node.name, node.moduleReference) :
|
|
isImportDeclaration(node) ? updateImportDeclaration(node, node.decorators, modifiers, node.importClause, node.moduleSpecifier) :
|
|
isExportAssignment(node) ? updateExportAssignment(node, node.decorators, modifiers, node.expression) :
|
|
isExportDeclaration(node) ? updateExportDeclaration(node, node.decorators, modifiers, node.isTypeOnly, node.exportClause, node.moduleSpecifier) :
|
|
Debug.assertNever(node);
|
|
}
|
|
|
|
function asNodeArray<T extends Node>(array: readonly T[]): NodeArray<T>;
|
|
function asNodeArray<T extends Node>(array: readonly T[] | undefined): NodeArray<T> | undefined;
|
|
function asNodeArray<T extends Node>(array: readonly T[] | undefined): NodeArray<T> | undefined {
|
|
return array ? createNodeArray(array) : undefined;
|
|
}
|
|
|
|
function asName<T extends DeclarationName | Identifier | BindingName | PropertyName | NoSubstitutionTemplateLiteral | EntityName | ThisTypeNode | undefined>(name: string | T): T | Identifier {
|
|
return typeof name === "string" ? createIdentifier(name) :
|
|
name;
|
|
}
|
|
|
|
function asExpression<T extends Expression | undefined>(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<TKind extends SyntaxKind>(value: TKind | Token<TKind>): Token<TKind> {
|
|
return typeof value === "number" ? createToken(value) : value;
|
|
}
|
|
|
|
function asEmbeddedStatement<T extends Node>(statement: T): T | EmptyStatement;
|
|
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined;
|
|
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined {
|
|
return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement;
|
|
}
|
|
}
|
|
|
|
function updateWithoutOriginal<T extends Node>(updated: T, original: T): T {
|
|
if (updated !== original) {
|
|
setTextRange(updated, original);
|
|
}
|
|
return updated;
|
|
}
|
|
|
|
function updateWithOriginal<T extends Node>(updated: T, original: T): T {
|
|
if (updated !== original) {
|
|
setOriginalNode(updated, original);
|
|
setTextRange(updated, original);
|
|
}
|
|
return updated;
|
|
}
|
|
|
|
function getDefaultTagNameForKind(kind: JSDocTag["kind"]): string {
|
|
switch (kind) {
|
|
case SyntaxKind.JSDocTypeTag: return "type";
|
|
case SyntaxKind.JSDocReturnTag: return "returns";
|
|
case SyntaxKind.JSDocThisTag: return "this";
|
|
case SyntaxKind.JSDocEnumTag: return "enum";
|
|
case SyntaxKind.JSDocAuthorTag: return "author";
|
|
case SyntaxKind.JSDocClassTag: return "class";
|
|
case SyntaxKind.JSDocPublicTag: return "public";
|
|
case SyntaxKind.JSDocPrivateTag: return "private";
|
|
case SyntaxKind.JSDocProtectedTag: return "protected";
|
|
case SyntaxKind.JSDocReadonlyTag: return "readonly";
|
|
case SyntaxKind.JSDocTemplateTag: return "template";
|
|
case SyntaxKind.JSDocTypedefTag: return "typedef";
|
|
case SyntaxKind.JSDocParameterTag: return "param";
|
|
case SyntaxKind.JSDocPropertyTag: return "prop";
|
|
case SyntaxKind.JSDocCallbackTag: return "callback";
|
|
case SyntaxKind.JSDocAugmentsTag: return "augments";
|
|
case SyntaxKind.JSDocImplementsTag: return "implements";
|
|
default:
|
|
return Debug.fail(`Unsupported kind: ${Debug.formatSyntaxKind(kind)}`);
|
|
}
|
|
}
|
|
|
|
let rawTextScanner: Scanner | undefined;
|
|
const invalidValueSentinel: object = { };
|
|
|
|
function getCookedText(kind: TemplateLiteralToken["kind"], rawText: string) {
|
|
if (!rawTextScanner) {
|
|
rawTextScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.Standard);
|
|
}
|
|
switch (kind) {
|
|
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
rawTextScanner.setText("`" + rawText + "`");
|
|
break;
|
|
case SyntaxKind.TemplateHead:
|
|
// tslint:disable-next-line no-invalid-template-strings
|
|
rawTextScanner.setText("`" + rawText + "${");
|
|
break;
|
|
case SyntaxKind.TemplateMiddle:
|
|
// tslint:disable-next-line no-invalid-template-strings
|
|
rawTextScanner.setText("}" + rawText + "${");
|
|
break;
|
|
case SyntaxKind.TemplateTail:
|
|
rawTextScanner.setText("}" + rawText + "`");
|
|
break;
|
|
}
|
|
|
|
let token = rawTextScanner.scan();
|
|
if (token === SyntaxKind.CloseBracketToken) {
|
|
token = rawTextScanner.reScanTemplateToken(/*isTaggedTemplate*/ false);
|
|
}
|
|
|
|
if (rawTextScanner.isUnterminated()) {
|
|
rawTextScanner.setText(undefined);
|
|
return invalidValueSentinel;
|
|
}
|
|
|
|
let tokenValue: string | undefined;
|
|
switch (token) {
|
|
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
case SyntaxKind.TemplateHead:
|
|
case SyntaxKind.TemplateMiddle:
|
|
case SyntaxKind.TemplateTail:
|
|
tokenValue = rawTextScanner.getTokenValue();
|
|
break;
|
|
}
|
|
|
|
if (tokenValue === undefined || rawTextScanner.scan() !== SyntaxKind.EndOfFileToken) {
|
|
rawTextScanner.setText(undefined);
|
|
return invalidValueSentinel;
|
|
}
|
|
|
|
rawTextScanner.setText(undefined);
|
|
return tokenValue;
|
|
}
|
|
|
|
function propagateIdentifierNameFlags(node: Identifier) {
|
|
// An IdentifierName is allowed to be `await`
|
|
return propagateChildFlags(node) & ~TransformFlags.ContainsPossibleTopLevelAwait;
|
|
}
|
|
|
|
function propagatePropertyNameFlagsOfChild(node: PropertyName, transformFlags: TransformFlags) {
|
|
return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags);
|
|
}
|
|
|
|
function propagateChildFlags(child: Node | undefined): TransformFlags {
|
|
if (!child) return TransformFlags.None;
|
|
const childFlags = child.transformFlags & ~getTransformFlagsSubtreeExclusions(child.kind);
|
|
return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlagsOfChild(child.name, childFlags) : childFlags;
|
|
}
|
|
|
|
function propagateChildrenFlags(children: NodeArray<Node> | undefined): TransformFlags {
|
|
return children ? children.transformFlags : TransformFlags.None;
|
|
}
|
|
|
|
function aggregateChildrenFlags(children: MutableNodeArray<Node>) {
|
|
let subtreeFlags = TransformFlags.None;
|
|
for (const child of children) {
|
|
subtreeFlags |= propagateChildFlags(child);
|
|
}
|
|
children.transformFlags = subtreeFlags;
|
|
}
|
|
|
|
/**
|
|
* Gets the transform flags to exclude when unioning the transform flags of a subtree.
|
|
*/
|
|
/* @internal */
|
|
export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) {
|
|
if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) {
|
|
return TransformFlags.TypeExcludes;
|
|
}
|
|
|
|
switch (kind) {
|
|
case SyntaxKind.CallExpression:
|
|
case SyntaxKind.NewExpression:
|
|
case SyntaxKind.ArrayLiteralExpression:
|
|
return TransformFlags.ArrayLiteralOrCallOrNewExcludes;
|
|
case SyntaxKind.ModuleDeclaration:
|
|
return TransformFlags.ModuleExcludes;
|
|
case SyntaxKind.Parameter:
|
|
return TransformFlags.ParameterExcludes;
|
|
case SyntaxKind.ArrowFunction:
|
|
return TransformFlags.ArrowFunctionExcludes;
|
|
case SyntaxKind.FunctionExpression:
|
|
case SyntaxKind.FunctionDeclaration:
|
|
return TransformFlags.FunctionExcludes;
|
|
case SyntaxKind.VariableDeclarationList:
|
|
return TransformFlags.VariableDeclarationListExcludes;
|
|
case SyntaxKind.ClassDeclaration:
|
|
case SyntaxKind.ClassExpression:
|
|
return TransformFlags.ClassExcludes;
|
|
case SyntaxKind.Constructor:
|
|
return TransformFlags.ConstructorExcludes;
|
|
case SyntaxKind.PropertyDeclaration:
|
|
return TransformFlags.PropertyExcludes;
|
|
case SyntaxKind.MethodDeclaration:
|
|
case SyntaxKind.GetAccessor:
|
|
case SyntaxKind.SetAccessor:
|
|
return TransformFlags.MethodOrAccessorExcludes;
|
|
case SyntaxKind.AnyKeyword:
|
|
case SyntaxKind.NumberKeyword:
|
|
case SyntaxKind.BigIntKeyword:
|
|
case SyntaxKind.NeverKeyword:
|
|
case SyntaxKind.StringKeyword:
|
|
case SyntaxKind.ObjectKeyword:
|
|
case SyntaxKind.BooleanKeyword:
|
|
case SyntaxKind.SymbolKeyword:
|
|
case SyntaxKind.VoidKeyword:
|
|
case SyntaxKind.TypeParameter:
|
|
case SyntaxKind.PropertySignature:
|
|
case SyntaxKind.MethodSignature:
|
|
case SyntaxKind.CallSignature:
|
|
case SyntaxKind.ConstructSignature:
|
|
case SyntaxKind.IndexSignature:
|
|
case SyntaxKind.InterfaceDeclaration:
|
|
case SyntaxKind.TypeAliasDeclaration:
|
|
return TransformFlags.TypeExcludes;
|
|
case SyntaxKind.ObjectLiteralExpression:
|
|
return TransformFlags.ObjectLiteralExcludes;
|
|
case SyntaxKind.CatchClause:
|
|
return TransformFlags.CatchClauseExcludes;
|
|
case SyntaxKind.ObjectBindingPattern:
|
|
case SyntaxKind.ArrayBindingPattern:
|
|
return TransformFlags.BindingPatternExcludes;
|
|
case SyntaxKind.TypeAssertionExpression:
|
|
case SyntaxKind.AsExpression:
|
|
case SyntaxKind.PartiallyEmittedExpression:
|
|
case SyntaxKind.ParenthesizedExpression:
|
|
case SyntaxKind.SuperKeyword:
|
|
return TransformFlags.OuterExpressionExcludes;
|
|
case SyntaxKind.PropertyAccessExpression:
|
|
case SyntaxKind.ElementAccessExpression:
|
|
return TransformFlags.PropertyAccessExcludes;
|
|
default:
|
|
return TransformFlags.NodeExcludes;
|
|
}
|
|
}
|
|
|
|
const baseFactory = createBaseNodeFactory();
|
|
|
|
function makeSynthetic(node: Node) {
|
|
(node as Mutable<Node>).flags |= NodeFlags.Synthesized;
|
|
return node;
|
|
}
|
|
|
|
const syntheticFactory: BaseNodeFactory = {
|
|
createBaseSourceFileNode: kind => makeSynthetic(baseFactory.createBaseSourceFileNode(kind)),
|
|
createBaseIdentifierNode: kind => makeSynthetic(baseFactory.createBaseIdentifierNode(kind)),
|
|
createBasePrivateIdentifierNode: kind => makeSynthetic(baseFactory.createBasePrivateIdentifierNode(kind)),
|
|
createBaseTokenNode: kind => makeSynthetic(baseFactory.createBaseTokenNode(kind)),
|
|
createBaseNode: kind => makeSynthetic(baseFactory.createBaseNode(kind)),
|
|
};
|
|
|
|
export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, syntheticFactory);
|
|
|
|
export function createUnparsedSourceFile(text: string): UnparsedSource;
|
|
export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource;
|
|
export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource;
|
|
export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, mapTextOrStripInternal?: string | boolean): UnparsedSource {
|
|
let stripInternal: boolean | undefined;
|
|
let bundleFileInfo: BundleFileInfo | undefined;
|
|
let fileName: string;
|
|
let text: string | undefined;
|
|
let length: number | (() => number);
|
|
let sourceMapPath: string | undefined;
|
|
let sourceMapText: string | undefined;
|
|
let getText: (() => string) | undefined;
|
|
let getSourceMapText: (() => string | undefined) | undefined;
|
|
let oldFileOfCurrentEmit: boolean | undefined;
|
|
|
|
if (!isString(textOrInputFiles)) {
|
|
Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts");
|
|
fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || "";
|
|
sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath : textOrInputFiles.declarationMapPath;
|
|
getText = () => mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText;
|
|
getSourceMapText = () => mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText;
|
|
length = () => getText!().length;
|
|
if (textOrInputFiles.buildInfo && textOrInputFiles.buildInfo.bundle) {
|
|
Debug.assert(mapTextOrStripInternal === undefined || typeof mapTextOrStripInternal === "boolean");
|
|
stripInternal = mapTextOrStripInternal;
|
|
bundleFileInfo = mapPathOrType === "js" ? textOrInputFiles.buildInfo.bundle.js : textOrInputFiles.buildInfo.bundle.dts;
|
|
oldFileOfCurrentEmit = textOrInputFiles.oldFileOfCurrentEmit;
|
|
}
|
|
}
|
|
else {
|
|
fileName = "";
|
|
text = textOrInputFiles;
|
|
length = textOrInputFiles.length;
|
|
sourceMapPath = mapPathOrType;
|
|
sourceMapText = mapTextOrStripInternal as string;
|
|
}
|
|
const node = oldFileOfCurrentEmit ?
|
|
parseOldFileOfCurrentEmit(Debug.assertDefined(bundleFileInfo)) :
|
|
parseUnparsedSourceFile(bundleFileInfo, stripInternal, length);
|
|
node.fileName = fileName;
|
|
node.sourceMapPath = sourceMapPath;
|
|
node.oldFileOfCurrentEmit = oldFileOfCurrentEmit;
|
|
if (getText && getSourceMapText) {
|
|
Object.defineProperty(node, "text", { get: getText });
|
|
Object.defineProperty(node, "sourceMapText", { get: getSourceMapText });
|
|
}
|
|
else {
|
|
Debug.assert(!oldFileOfCurrentEmit);
|
|
node.text = text ?? "";
|
|
node.sourceMapText = sourceMapText;
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
function parseUnparsedSourceFile(bundleFileInfo: BundleFileInfo | undefined, stripInternal: boolean | undefined, length: number | (() => number)) {
|
|
let prologues: UnparsedPrologue[] | undefined;
|
|
let helpers: UnscopedEmitHelper[] | undefined;
|
|
let referencedFiles: FileReference[] | undefined;
|
|
let typeReferenceDirectives: string[] | undefined;
|
|
let libReferenceDirectives: FileReference[] | undefined;
|
|
let prependChildren: UnparsedTextLike[] | undefined;
|
|
let texts: UnparsedSourceText[] | undefined;
|
|
let hasNoDefaultLib: boolean | undefined;
|
|
|
|
for (const section of bundleFileInfo ? bundleFileInfo.sections : emptyArray) {
|
|
switch (section.kind) {
|
|
case BundleFileSectionKind.Prologue:
|
|
prologues = append(prologues, setTextRange(factory.createUnparsedPrologue(section.data), section));
|
|
break;
|
|
case BundleFileSectionKind.EmitHelpers:
|
|
helpers = append(helpers, getAllUnscopedEmitHelpers().get(section.data)!);
|
|
break;
|
|
case BundleFileSectionKind.NoDefaultLib:
|
|
hasNoDefaultLib = true;
|
|
break;
|
|
case BundleFileSectionKind.Reference:
|
|
referencedFiles = append(referencedFiles, { pos: -1, end: -1, fileName: section.data });
|
|
break;
|
|
case BundleFileSectionKind.Type:
|
|
typeReferenceDirectives = append(typeReferenceDirectives, section.data);
|
|
break;
|
|
case BundleFileSectionKind.Lib:
|
|
libReferenceDirectives = append(libReferenceDirectives, { pos: -1, end: -1, fileName: section.data });
|
|
break;
|
|
case BundleFileSectionKind.Prepend:
|
|
let prependTexts: UnparsedTextLike[] | undefined;
|
|
for (const text of section.texts) {
|
|
if (!stripInternal || text.kind !== BundleFileSectionKind.Internal) {
|
|
prependTexts = append(prependTexts, setTextRange(factory.createUnparsedTextLike(text.data, text.kind === BundleFileSectionKind.Internal), text));
|
|
}
|
|
}
|
|
prependChildren = addRange(prependChildren, prependTexts);
|
|
texts = append(texts, factory.createUnparsedPrepend(section.data, prependTexts ?? emptyArray));
|
|
break;
|
|
case BundleFileSectionKind.Internal:
|
|
if (stripInternal) {
|
|
if (!texts) texts = [];
|
|
break;
|
|
}
|
|
// falls through
|
|
|
|
case BundleFileSectionKind.Text:
|
|
texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), section));
|
|
break;
|
|
default:
|
|
Debug.assertNever(section);
|
|
}
|
|
}
|
|
|
|
if (!texts) {
|
|
const textNode = factory.createUnparsedTextLike(/*data*/ undefined, /*internal*/ false);
|
|
setTextRangePosWidth(textNode, 0, typeof length === "function" ? length() : length);
|
|
texts = [textNode];
|
|
}
|
|
|
|
const node = parseNodeFactory.createUnparsedSource(prologues ?? emptyArray, /*syntheticReferences*/ undefined, texts);
|
|
setEachParent(prologues, node);
|
|
setEachParent(texts, node);
|
|
setEachParent(prependChildren, node);
|
|
node.hasNoDefaultLib = hasNoDefaultLib;
|
|
node.helpers = helpers;
|
|
node.referencedFiles = referencedFiles || emptyArray;
|
|
node.typeReferenceDirectives = typeReferenceDirectives;
|
|
node.libReferenceDirectives = libReferenceDirectives || emptyArray;
|
|
return node;
|
|
}
|
|
|
|
function parseOldFileOfCurrentEmit(bundleFileInfo: BundleFileInfo) {
|
|
let texts: UnparsedTextLike[] | undefined;
|
|
let syntheticReferences: UnparsedSyntheticReference[] | undefined;
|
|
for (const section of bundleFileInfo.sections) {
|
|
switch (section.kind) {
|
|
case BundleFileSectionKind.Internal:
|
|
case BundleFileSectionKind.Text:
|
|
texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), section));
|
|
break;
|
|
|
|
case BundleFileSectionKind.NoDefaultLib:
|
|
case BundleFileSectionKind.Reference:
|
|
case BundleFileSectionKind.Type:
|
|
case BundleFileSectionKind.Lib:
|
|
syntheticReferences = append(syntheticReferences, setTextRange(factory.createUnparsedSyntheticReference(section), section));
|
|
break;
|
|
|
|
// Ignore
|
|
case BundleFileSectionKind.Prologue:
|
|
case BundleFileSectionKind.EmitHelpers:
|
|
case BundleFileSectionKind.Prepend:
|
|
break;
|
|
|
|
default:
|
|
Debug.assertNever(section);
|
|
}
|
|
}
|
|
|
|
const node = factory.createUnparsedSource(emptyArray, syntheticReferences, texts ?? emptyArray);
|
|
setEachParent(syntheticReferences, node);
|
|
setEachParent(texts, node);
|
|
node.helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!);
|
|
return node;
|
|
}
|
|
|
|
// TODO(rbuckton): Move part of this to factory
|
|
export function createInputFiles(
|
|
javascriptText: string,
|
|
declarationText: string
|
|
): InputFiles;
|
|
export function createInputFiles(
|
|
readFileText: (path: string) => string | undefined,
|
|
javascriptPath: string,
|
|
javascriptMapPath: string | undefined,
|
|
declarationPath: string,
|
|
declarationMapPath: string | undefined,
|
|
buildInfoPath: string | undefined
|
|
): InputFiles;
|
|
export function createInputFiles(
|
|
javascriptText: string,
|
|
declarationText: string,
|
|
javascriptMapPath: string | undefined,
|
|
javascriptMapText: string | undefined,
|
|
declarationMapPath: string | undefined,
|
|
declarationMapText: string | undefined
|
|
): InputFiles;
|
|
/*@internal*/
|
|
export function createInputFiles(
|
|
javascriptText: string,
|
|
declarationText: string,
|
|
javascriptMapPath: string | undefined,
|
|
javascriptMapText: string | undefined,
|
|
declarationMapPath: string | undefined,
|
|
declarationMapText: string | undefined,
|
|
javascriptPath: string | undefined,
|
|
declarationPath: string | undefined,
|
|
buildInfoPath?: string | undefined,
|
|
buildInfo?: BuildInfo,
|
|
oldFileOfCurrentEmit?: boolean
|
|
): InputFiles;
|
|
export function createInputFiles(
|
|
javascriptTextOrReadFileText: string | ((path: string) => string | undefined),
|
|
declarationTextOrJavascriptPath: string,
|
|
javascriptMapPath?: string,
|
|
javascriptMapTextOrDeclarationPath?: string,
|
|
declarationMapPath?: string,
|
|
declarationMapTextOrBuildInfoPath?: string,
|
|
javascriptPath?: string | undefined,
|
|
declarationPath?: string | undefined,
|
|
buildInfoPath?: string | undefined,
|
|
buildInfo?: BuildInfo,
|
|
oldFileOfCurrentEmit?: boolean
|
|
): InputFiles {
|
|
const node = parseNodeFactory.createInputFiles();
|
|
if (!isString(javascriptTextOrReadFileText)) {
|
|
const cache = new Map<string, string | false>();
|
|
const textGetter = (path: string | undefined) => {
|
|
if (path === undefined) return undefined;
|
|
let value = cache.get(path);
|
|
if (value === undefined) {
|
|
value = javascriptTextOrReadFileText(path);
|
|
cache.set(path, value !== undefined ? value : false);
|
|
}
|
|
return value !== false ? value as string : undefined;
|
|
};
|
|
const definedTextGetter = (path: string) => {
|
|
const result = textGetter(path);
|
|
return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`;
|
|
};
|
|
let buildInfo: BuildInfo | false;
|
|
const getAndCacheBuildInfo = (getText: () => string | undefined) => {
|
|
if (buildInfo === undefined) {
|
|
const result = getText();
|
|
buildInfo = result !== undefined ? getBuildInfo(result) : false;
|
|
}
|
|
return buildInfo || undefined;
|
|
};
|
|
node.javascriptPath = declarationTextOrJavascriptPath;
|
|
node.javascriptMapPath = javascriptMapPath;
|
|
node.declarationPath = Debug.assertDefined(javascriptMapTextOrDeclarationPath);
|
|
node.declarationMapPath = declarationMapPath;
|
|
node.buildInfoPath = declarationMapTextOrBuildInfoPath;
|
|
Object.defineProperties(node, {
|
|
javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } },
|
|
javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that
|
|
declarationText: { get() { return definedTextGetter(Debug.assertDefined(javascriptMapTextOrDeclarationPath)); } },
|
|
declarationMapText: { get() { return textGetter(declarationMapPath); } }, // TODO:: if there is inline sourceMap in dtsFile, use that
|
|
buildInfo: { get() { return getAndCacheBuildInfo(() => textGetter(declarationMapTextOrBuildInfoPath)); } }
|
|
});
|
|
}
|
|
else {
|
|
node.javascriptText = javascriptTextOrReadFileText;
|
|
node.javascriptMapPath = javascriptMapPath;
|
|
node.javascriptMapText = javascriptMapTextOrDeclarationPath;
|
|
node.declarationText = declarationTextOrJavascriptPath;
|
|
node.declarationMapPath = declarationMapPath;
|
|
node.declarationMapText = declarationMapTextOrBuildInfoPath;
|
|
node.javascriptPath = javascriptPath;
|
|
node.declarationPath = declarationPath;
|
|
node.buildInfoPath = buildInfoPath;
|
|
node.buildInfo = buildInfo;
|
|
node.oldFileOfCurrentEmit = oldFileOfCurrentEmit;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// tslint:disable-next-line variable-name
|
|
let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
|
|
|
|
/**
|
|
* Create an external source map source file reference
|
|
*/
|
|
export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource {
|
|
return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia);
|
|
}
|
|
|
|
// Utilities
|
|
|
|
export function setOriginalNode<T extends Node>(node: T, original: Node | undefined): T {
|
|
node.original = original;
|
|
if (original) {
|
|
const emitNode = original.emitNode;
|
|
if (emitNode) node.emitNode = mergeEmitNode(emitNode, node.emitNode);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefined) {
|
|
const {
|
|
flags,
|
|
leadingComments,
|
|
trailingComments,
|
|
commentRange,
|
|
sourceMapRange,
|
|
tokenSourceMapRanges,
|
|
constantValue,
|
|
helpers,
|
|
startsOnNewLine,
|
|
} = sourceEmitNode;
|
|
if (!destEmitNode) destEmitNode = {} as EmitNode;
|
|
// We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later.
|
|
if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
|
|
if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
|
|
if (flags) destEmitNode.flags = flags;
|
|
if (commentRange) destEmitNode.commentRange = commentRange;
|
|
if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange;
|
|
if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges!);
|
|
if (constantValue !== undefined) destEmitNode.constantValue = constantValue;
|
|
if (helpers) {
|
|
for (const helper of helpers) {
|
|
destEmitNode.helpers = appendIfUnique(destEmitNode.helpers, helper);
|
|
}
|
|
}
|
|
if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine;
|
|
return destEmitNode;
|
|
}
|
|
|
|
function mergeTokenSourceMapRanges(sourceRanges: (TextRange | undefined)[], destRanges: (TextRange | undefined)[]) {
|
|
if (!destRanges) destRanges = [];
|
|
for (const key in sourceRanges) {
|
|
destRanges[key] = sourceRanges[key];
|
|
}
|
|
return destRanges;
|
|
}
|
|
}
|