import { DefinitionFlags , NodeFlags , NodeKind , OrderKind , TypeFlags } from '#ast/enums' ; import { AnonymousClass , AnonymousFunctionNode , AnythingNode , ArrayNode , BooleanNode , ByteNode , CharacterNode , ClassDeclaration , ComplexNumberNode , DateNode , DateTimeLiteral , DateTimeNode , DecimalLiteral , DecimalNode , Definition , EnumDeclaration , EnumMemberDeclaration , FalseLiteral , FunctionDeclaration , GenericIterable , ImaginaryNumberLiteral , InfinityNode , IntegerLiteral , IntegerNode , InterfaceDeclaration , IntersectionNode , LinkedListNode , ListNode , MapNode , MethodDeclaration , ModuleDeclaration , MultiSetNode , NamedNode , Node , NotANumberNode , NothingNode , NullNode , ObjectNode , ObjectNodeBase , ParameterNode , PropertyDeclaration , ReferenceNode , RegExpLiteral , RegExpNode , SetNode , SignatureNode , SourceFile , StringLiteral , StringNode , SymbolLiteral , SymbolNode , TrueLiteral , TupleNode , TypeArgumentNode , TypeDeclaration , TypeParameterDeclaration , UnionNode , VariableDeclaration } from '#ast/node-types' ; import { omit } from '@crosstype/common' ; import { NodeForKind } from '#ast/node-lookups' ; import { NodeObject } from '#ast/node-object' ; import { isClassDeclaration , isDefinition , isEnumDeclaration , isFunctionDeclaration , isInterfaceDeclaration , isMethodDeclaration , isNamedNode , isNode , isPropertyDeclaration , isSourceFile , isTypeDeclaration , isVariableDeclaration } from '#ast/utilities/node-typeguards' ; import { NodeMap , NodeSet } from '#ast/components' ; import { cloneNode } from '#ast/utilities/clone-node' ; import { nodeMetadata } from '#ast/node-metadata' ; import { Declaration } from '#ast/node-aliases' ; import { findTargetDeclarationsByPath } from '#ast/utilities/find-target-declarations-by-path' ; import { NodeIndex } from '#ast' ; const getObjectLikeNodeDescriptors = ( ) : PropertyDescriptorMap => ( { properties : { get ( this ) { return new NodeMap ( this . members . toArray ( ) . filter ( isPropertyDeclaration ) ) ; } } , methods : { get ( this ) { return new NodeMap ( this . members . toArray ( ) . filter ( isMethodDeclaration ) ) ; } } } ) ; const getNamedNodeDescriptors = ( ) : PropertyDescriptorMap => { let name ; return ( { name : { get ( this ) { return name ; } , set ( this , newName ) { name = newName ; this . updateNameOnParentContainer ( ) ; } , enumerable : true } } ) ; } ; returns type CreateNodeProperties < T > = Partial < Pick < T , { [ K in keyof T ] : T [ K ] extends Function ? never : K extends 'kind' ? never : K ; } [ keyof T ] > > ; returns type NodeProperties < T extends Node , Exclusions extends keyof T = never > = Pick < T , { [ K in keyof T ] : T [ K ] extends Function ? never : K extends Exclusions ? never : K extends Exclude < keyof Node , 'origin' | 'compileOptions' > ? never : K ; } [ keyof T ] > ; internal export function createNode < K extends NodeKind > ( kind , properties , additionalDescriptors ? ) ; export function createNode < T extends Node > ( kind , properties , additionalDescriptors ? ) ; export function createNode ( kind , properties , additionalDescriptors ? ) { properties = Object . assign ( { } , properties ) ; const node = new NodeObject ( kind , properties . origin , properties . compileOptions ) ; const { baseTypeFlags , baseFlags , childContainerProperties , isNamedNode } = nodeMetadata [ kind ] ; const flags = ( properties . flags || NodeFlags . None ) | ( baseFlags ?. reduce ( ( p , c ) => p + c ) || 0 ) ; const typeFlags = ( properties . typeFlags || TypeFlags . None ) | ( baseTypeFlags ?. reduce ( ( p , c ) => p + c ) || 0 ) ; if ( isNamedNode ) additionalDescriptors = Object . assign ( { } , getNamedNodeDescriptors ( ) , additionalDescriptors ) ; if ( additionalDescriptors ) Object . defineProperties ( node , additionalDescriptors ) ; for ( const key of childContainerProperties ?. keys ( ) || [ ] ) { if ( properties . hasOwnProperty ( key ) ) { const item = ( < any > properties ) [ key ] ; if ( isNode ( item ) && item . parent ) ( < any > properties ) [ key ] = cloneNode ( item ) ; else if ( item instanceof NodeMap && item . find ( n => ! ! n . parent ) ) ( < any > properties ) [ key ] = NodeMap . from ( item . values ( ) , node => { return ( ! node . parent ) ? node : cloneNode ( node ) ; } ) ; else if ( item instanceof NodeSet && item . find ( n => ! ! n . parent ) ) ( < any > properties ) [ key ] = NodeSet . from ( item , node => { return ( ! node . parent ) ? node : cloneNode ( node ) ; } ) ; } } Object . assign ( node , omit ( properties , 'origin' , 'compileOptions' ) , { flags , typeFlags } ) ; node . fixup ( ) ; return node ; } export function createDefinition ( properties ) { const desc = { definitionFlags : { get ( this ) { let res = DefinitionFlags . None | ( + ( this . declarations . size > 1 ) && DefinitionFlags . HasMultipleDeclarations ) | ( + ( ! ! this . typeArguments && this . typeArguments . size > 0 ) && DefinitionFlags . Parameterized ) ; for ( const declaration of this . declarations . values ( ) ) res |= isFunctionDeclaration ( declaration ) ? DefinitionFlags . Function : isTypeDeclaration ( declaration ) ? DefinitionFlags . Type : isClassDeclaration ( declaration ) ? DefinitionFlags . Class : isInterfaceDeclaration ( declaration ) ? DefinitionFlags . Interface : isEnumDeclaration ( declaration ) ? DefinitionFlags . Enum : isVariableDeclaration ( declaration ) ? DefinitionFlags . Variable : 0 ; return res ; } } } ; return createNode ( NodeKind . Definition , properties , desc ) ; } export function createNamespaceNode ( properties ) { return createNode ( NodeKind . ModuleDeclaration , properties ) ; } export function createSourceFile ( properties ) { return createNode ( NodeKind . SourceFile , properties ) ; } export function createStringNode ( properties ) { return createNode ( NodeKind . String , properties ) ; } export function createCharacterNode ( properties ) { return createNode ( NodeKind . Character , properties ) ; } export function createByteNode ( properties ) { return createNode ( NodeKind . Byte , properties ) ; } export function createRegExpNode ( properties ) { return createNode ( NodeKind . RegExp , properties ) ; } export function createSymbolNode ( properties ) { return createNode ( NodeKind . Symbol , properties ) ; } export function createBooleanNode ( properties ) { return createNode ( NodeKind . Boolean , properties ) ; } export function createIntegerNode ( properties ? ) { return createNode ( NodeKind . Integer , properties || { } ) ; } export function createDecimalNumberNode ( properties ) { return createNode ( NodeKind . Decimal , properties ) ; } export function createComplexNumberNode ( properties ) { return createNode ( NodeKind . ComplexNumber , properties ) ; } export function createNotANumberNode ( properties ) { return createNode ( NodeKind . NotANumber , properties ) ; } export function createInfinityNode ( properties ) { return createNode ( NodeKind . Infinity , properties ) ; } export function createStringLiteral ( properties ) { return createNode ( NodeKind . StringLiteral , properties ) ; } export function createTrueLiteral ( properties ? ) { return createNode ( NodeKind . TrueLiteral , properties || { } ) ; } export function createFalseLiteral ( properties ? ) { return createNode ( NodeKind . FalseLiteral , properties || { } ) ; } export function createRegExpLiteral ( properties ) { return createNode ( NodeKind . RegExpLiteral , properties ) ; } export function createDateTimeLiteral ( properties ) { return createNode ( NodeKind . DateTimeLiteral , properties ) ; } export function createSymbolLiteral ( properties ) { return createNode ( NodeKind . SymbolLiteral , properties ) ; } export function createIntegerLiteral ( properties ) { return createNode ( NodeKind . IntegerLiteral , properties ) ; } export function createDecimalLiteral ( properties ) { return createNode ( NodeKind . DecimalLiteral , properties ) ; } export function createImaginaryNumberLiteral ( properties ) { return createNode ( NodeKind . ImaginaryNumberLiteral , properties ) ; } export function createGenericIterable ( properties ) { return createNode ( NodeKind . GenericIterable , properties ) ; } export function createArrayNode ( properties ) { const props = Object . assign ( { } , properties , { orderKind : < const > OrderKind . Index , indexType : createIntegerNode ( ) } ) ; return createNode ( NodeKind . Array , props ) ; } export function createMapNode ( properties ) { const props = Object . assign ( { } , properties , < const > { resizable : true , uniqueMembers : true , orderKind : OrderKind . Index } ) ; return createNode ( NodeKind . Map , props ) ; } export function createMultiSetNode ( properties ) { const props = Object . assign ( { } , properties , < const > { uniqueMembers : false , } ) ; return createNode ( NodeKind . MultiSet , props ) ; } export function createSetNode ( properties ) { const props = Object . assign ( { } , properties , < const > { uniqueMembers : true , } ) ; return createNode ( NodeKind . Set , props ) ; } export function createListNode ( properties ) { const props = Object . assign ( { } , properties , < const > { resizable : true , orderKind : < const > OrderKind . Index , indexType : createIntegerNode ( ) } ) ; return createNode ( NodeKind . List , props ) ; } export function createLinkedListNode ( properties ) { const props = Object . assign ( { } , properties , { orderKind : < const > OrderKind . Link } ) ; return createNode ( NodeKind . LinkedList , props ) ; } export function createEnumDeclaration ( properties ) { const desc = { keys : { get ( this ) { return [ ... this . members . keys ( ) ] ; } } , values : { get ( this ) { return [ ... this . members . values ( ) ] ; } } } ; return createNode ( NodeKind . EnumDeclaration , properties , desc ) ; } export function createEnumMemberDeclaration ( properties ) { return createNode ( NodeKind . EnumMemberDeclaration , properties ) ; } export function createTupleNode ( properties ) { return createNode ( NodeKind . Tuple , properties ) ; } export function createObjectNode ( properties ) { return createNode ( NodeKind . Object , properties , getObjectLikeNodeDescriptors ( ) ) ; } export function createClassDeclaration ( properties ) { return createNode ( NodeKind . ClassDeclaration , properties , getObjectLikeNodeDescriptors ( ) ) ; } export function createAnonymousClass ( properties ) { return createNode ( NodeKind . AnonymousClass , properties , getObjectLikeNodeDescriptors ( ) ) ; } export function createInterfaceDeclaration ( properties ) { return createNode ( NodeKind . InterfaceDeclaration , properties , getObjectLikeNodeDescriptors ( ) ) ; } export function createPropertyDeclaration ( properties ) { return createNode ( NodeKind . PropertyDeclaration , properties ) ; } export function createMethodDeclaration ( properties ) { return createNode ( NodeKind . MethodDeclaration , properties ) ; } export function createDateNode ( properties ? ) { return createNode ( NodeKind . Date , properties || { } ) ; } export function createDateTimeNode ( properties ? ) { return createNode ( NodeKind . DateTime , properties || { } ) ; } export function createFunctionDeclaration ( properties ) { return createNode ( NodeKind . FunctionDeclaration , properties ) ; } export function createAnonymousFunctionNode ( properties ) { return createNode ( NodeKind . AnonymousFunction , properties ) ; } export function createSignatureNode ( properties ) { return createNode ( NodeKind . Signature , properties ) ; } export function createParameterNode ( properties ) { return createNode ( NodeKind . Parameter , properties ) ; } export function createTypeParameterDeclaration ( properties ) { return createNode ( NodeKind . TypeParameterDeclaration , properties ) ; } export function createTypeArgumentNode ( properties ) { const desc = { name : { get ( this ) { return this . association . name ; } } } ; return createNode ( NodeKind . TypeArgument , properties , desc ) ; } export function createTypeDeclaration ( properties ) { return createNode ( NodeKind . TypeDeclaration , properties ) ; } export function createVariableDeclaration ( properties ) { return createNode ( NodeKind . VariableDeclaration , properties ) ; } export function createUnionNode ( properties ) { return createNode ( NodeKind . Union , properties ) ; } export function createIntersectionNode ( properties ) { return createNode ( NodeKind . Intersection , properties ) ; } export function createTopNode ( properties ? ) { return createAnythingNode ( properties ) ; } export function createBottomNode ( properties ? ) { return createNothingNode ( properties ) ; } export function createAnythingNode ( properties ? ) { return createNode ( NodeKind . Anything , properties || { } ) ; } export function createNothingNode ( properties ? ) { return createNode ( NodeKind . Nothing , properties || { } ) ; } export function createNullNode ( properties ? ) { return createNode ( NodeKind . Null , properties || { } ) ; } export function createReferenceNode ( properties ) ; internal export function createReferenceNode ( properties ) ; export function createReferenceNode ( properties ) { let target ; const desc = { target : { get ( this ) { updatePath ( this ) ; if ( target ) return target ; const foundTarget = findTargetDeclarationsByPath ( this . targetBase , this . path ) ?. [ 0 ] ; if ( foundTarget ) this . target = foundTarget ; return target ! ; } , set ( this , newTarget ) { const oldTarget = target ; target = newTarget ; updatePath ( this ) ; if ( oldTarget !== target ) { ( oldTarget ?. getReferencesToThisNode ( ) as NodeSet < ReferenceNode > | undefined ) ?. delete ( this ) ; ( target . getReferencesToThisNode ( ) as NodeSet < ReferenceNode > | undefined ) ?. add ( this ) ; } } , } , } ; return createNode ( NodeKind . Reference , properties , desc ) ; function updatePath ( ref ) { if ( ! target || ! target . parent ) return ; ref . targetBase = target . getDefinition ( ) ! ; const refPath = [ ] ; for ( let node = target ; node && ! isDefinition ( node ) && ! isSourceFile ( node ) ; node = node . parent ) if ( isNamedNode ( node ) ) refPath . unshift ( node . name ) ; ref . path = refPath ; } }