2020-06-17 01:55:03 +02:00
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 ) ; } ,
2020-06-19 02:41:26 +02:00
get createJSDocDeprecatedTag() { return getJSDocSimpleTagCreateFunction < JSDocDeprecatedTag > ( SyntaxKind . JSDocDeprecatedTag ) ; } ,
get updateJSDocDeprecatedTag() { return getJSDocSimpleTagUpdateFunction < JSDocDeprecatedTag > ( SyntaxKind . JSDocDeprecatedTag ) ; } ,
2020-06-17 01:55:03 +02:00
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 > ) ;
}
2020-09-03 05:05:50 +02:00
Debug . attachNodeArrayDebugInfo ( elements ) ;
2020-06-17 01:55:03 +02:00
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 ) ;
2020-09-03 05:05:50 +02:00
Debug . attachNodeArrayDebugInfo ( array ) ;
2020-06-17 01:55:03 +02:00
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
) ;
2020-06-19 08:43:18 +02:00
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 ;
}
}
2020-06-17 01:55:03 +02:00
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 ;
2020-06-19 08:43:18 +02:00
node . transformFlags |= propagateChildFlags ( node . body ) & ~ TransformFlags . ContainsPossibleTopLevelAwait ;
2020-06-17 01:55:03 +02:00
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 ) ;
}
2020-06-19 08:43:18 +02:00
if ( node . originalKeywordKind === SyntaxKind . AwaitKeyword ) {
node . transformFlags |= TransformFlags . ContainsPossibleTopLevelAwait ;
}
2020-06-17 01:55:03 +02:00
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 ) |
2020-06-19 08:43:18 +02:00
propagateIdentifierNameFlags ( node . right ) ;
2020-06-17 01:55:03 +02:00
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 ;
2020-06-19 08:43:18 +02:00
if ( node . propertyName ) {
node . transformFlags |= isIdentifier ( node . propertyName ) ?
propagateIdentifierNameFlags ( node . propertyName ) :
propagateChildFlags ( node . propertyName ) ;
}
2020-06-17 01:55:03 +02:00
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 ) |
2020-06-19 08:43:18 +02:00
( isIdentifier ( node . name ) ?
propagateIdentifierNameFlags ( node . name ) :
propagateChildFlags ( node . name ) ) ;
2020-06-17 01:55:03 +02:00
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 |=
2020-06-19 08:43:18 +02:00
TransformFlags . ContainsES2020 |
2020-06-17 01:55:03 +02:00
propagateChildFlags ( node . expression ) |
propagateChildFlags ( node . questionDotToken ) |
2020-06-19 08:43:18 +02:00
( isIdentifier ( node . name ) ?
propagateIdentifierNameFlags ( node . name ) :
propagateChildFlags ( node . name ) ) ;
2020-06-17 01:55:03 +02:00
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 ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // Enum declarations cannot contain `await`
2020-06-17 01:55:03 +02:00
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 ;
}
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // Module declarations cannot contain `await`.
2020-06-17 01:55:03 +02:00
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 ,
module Reference : ModuleReference
) {
const node = createBaseNamedDeclaration < ImportEqualsDeclaration > (
SyntaxKind . ImportEqualsDeclaration ,
decorators ,
modifiers ,
name
) ;
node . module Reference = module Reference ;
node . transformFlags |= propagateChildFlags ( node . module Reference ) ;
if ( ! isExternalModuleReference ( node . module Reference ) ) node . transformFlags |= TransformFlags . ContainsTypeScript ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // Import= declaration is always parsed in an Await context
2020-06-17 01:55:03 +02:00
return node ;
}
// @api
function updateImportEqualsDeclaration (
node : ImportEqualsDeclaration ,
decorators : readonly Decorator [ ] | undefined ,
modifiers : readonly Modifier [ ] | undefined ,
name : Identifier ,
module Reference : ModuleReference
) {
return node . decorators !== decorators
|| node . modifiers !== modifiers
|| node . name !== name
|| node . module Reference !== module Reference
? update ( createImportEqualsDeclaration ( decorators , modifiers , name , module Reference ) , node )
: node ;
}
// @api
function createImportDeclaration (
decorators : readonly Decorator [ ] | undefined ,
modifiers : readonly Modifier [ ] | undefined ,
importClause : ImportClause | undefined ,
module Specifier : Expression
) : ImportDeclaration {
const node = createBaseDeclaration < ImportDeclaration > (
SyntaxKind . ImportDeclaration ,
decorators ,
modifiers
) ;
node . importClause = importClause ;
node . module Specifier = module Specifier ;
node . transformFlags |=
propagateChildFlags ( node . importClause ) |
propagateChildFlags ( node . module Specifier ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
return node ;
}
// @api
function updateImportDeclaration (
node : ImportDeclaration ,
decorators : readonly Decorator [ ] | undefined ,
modifiers : readonly Modifier [ ] | undefined ,
importClause : ImportClause | undefined ,
module Specifier : Expression
) {
return node . decorators !== decorators
|| node . modifiers !== modifiers
|| node . importClause !== importClause
|| node . module Specifier !== module Specifier
? update ( createImportDeclaration ( decorators , modifiers , importClause , module Specifier ) , 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 ;
}
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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 ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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 ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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 ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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 ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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 ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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 ,
module Specifier? : Expression
) {
const node = createBaseDeclaration < ExportDeclaration > (
SyntaxKind . ExportDeclaration ,
decorators ,
modifiers
) ;
node . isTypeOnly = isTypeOnly ;
node . exportClause = exportClause ;
node . module Specifier = module Specifier ;
node . transformFlags |=
propagateChildFlags ( node . exportClause ) |
propagateChildFlags ( node . module Specifier ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
return node ;
}
// @api
function updateExportDeclaration (
node : ExportDeclaration ,
decorators : readonly Decorator [ ] | undefined ,
modifiers : readonly Modifier [ ] | undefined ,
isTypeOnly : boolean ,
exportClause : NamedExportBindings | undefined ,
module Specifier : Expression | undefined
) {
return node . decorators !== decorators
|| node . modifiers !== modifiers
|| node . isTypeOnly !== isTypeOnly
|| node . exportClause !== exportClause
|| node . module Specifier !== module Specifier
? update ( createExportDeclaration ( decorators , modifiers , isTypeOnly , exportClause , module Specifier ) , node )
: node ;
}
// @api
function createNamedExports ( elements : readonly ExportSpecifier [ ] ) {
const node = createBaseNode < NamedExports > ( SyntaxKind . NamedExports ) ;
node . elements = createNodeArray ( elements ) ;
node . transformFlags |= propagateChildrenFlags ( node . elements ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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 ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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 ) ;
2020-06-19 08:43:18 +02:00
node . transformFlags &= ~ TransformFlags . ContainsPossibleTopLevelAwait ; // always parsed in an Await context
2020-06-17 01:55:03 +02:00
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
2020-06-19 02:41:26 +02:00
// createJSDocDeprecatedTag
2020-06-17 01:55:03 +02:00
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
2020-06-19 02:41:26 +02:00
// updateJSDocDeprecatedTag
2020-06-17 01:55:03 +02:00
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 {
2020-06-26 01:03:25 +02:00
const leftPrologues = new Map < string , boolean > ( ) ;
2020-06-17 01:55:03 +02:00
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 . module Reference ) :
isImportDeclaration ( node ) ? updateImportDeclaration ( node , node . decorators , modifiers , node . importClause , node . module Specifier ) :
isExportAssignment ( node ) ? updateExportAssignment ( node , node . decorators , modifiers , node . expression ) :
isExportDeclaration ( node ) ? updateExportDeclaration ( node , node . decorators , modifiers , node . isTypeOnly , node . exportClause , node . module Specifier ) :
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 ;
}
2020-06-19 08:43:18 +02:00
function propagateIdentifierNameFlags ( node : Identifier ) {
// An IdentifierName is allowed to be `await`
return propagateChildFlags ( node ) & ~ TransformFlags . ContainsPossibleTopLevelAwait ;
}
function propagatePropertyNameFlagsOfChild ( node : PropertyName , transformFlags : TransformFlags ) {
2020-06-17 01:55:03 +02:00
return transformFlags | ( node . transformFlags & TransformFlags . PropertyNamePropagatingFlags ) ;
}
function propagateChildFlags ( child : Node | undefined ) : TransformFlags {
if ( ! child ) return TransformFlags . None ;
const childFlags = child . transformFlags & ~ getTransformFlagsSubtreeExclusions ( child . kind ) ;
2020-06-19 08:43:18 +02:00
return isNamedDeclaration ( child ) && isPropertyName ( child . name ) ? propagatePropertyNameFlagsOfChild ( child . name , childFlags ) : childFlags ;
2020-06-17 01:55:03 +02:00
}
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 ) ) {
2020-06-26 01:03:25 +02:00
const cache = new Map < string , string | false > ( ) ;
2020-06-17 01:55:03 +02:00
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 ;
}
}