import * as PQLS from "@microsoft/powerquery-language-services" ; import * as PQP from "@microsoft/powerquery-parser" ; import { Type , TypeUtils } from "@microsoft/powerquery-parser/lib/powerquery-parser/language" ; export function createStandardLibraryTypeResolver ( libraryDefinitions ) { return ( request ) => { const maybeLibraryType = libraryDefinitions . get ( request . identifierLiteral ) ?. asPowerQueryType ; if ( maybeLibraryType === undefined ) { return undefined ; } else if ( request . kind === PQLS . Inspection . ExternalType . ExternalTypeRequestKind . Value ) { return maybeLibraryType ; } else { const key = TypeUtils . nameOf ( maybeLibraryType ) ; const maybeSmartTypeResolverFn = SmartTypeResolverFns . get ( key ) ; if ( maybeSmartTypeResolverFn === undefined ) { return undefined ; } const typeChecked = TypeUtils . typeCheckInvocation ( request . args , TypeUtils . assertAsDefinedFunction ( maybeLibraryType ) ) ; if ( ! isValidInvocation ( typeChecked ) ) { return undefined ; } return maybeSmartTypeResolverFn ( request . args ) ; } } ; } type SmartTypeResolverFn = ( args : ReadonlyArray < Type . TPowerQueryType > ) => Type . TPowerQueryType | undefined ; function isValidInvocation ( typeChecked ) { return ! typeChecked . extraneous . length && ! typeChecked . invalid . size && ! typeChecked . missing . length ; } function resolveTableAddColumn ( args ) { const table = TypeUtils . assertAsTable ( PQP . Assert . asDefined ( args [ 0 ] ) ) ; const columnName = TypeUtils . assertAsText ( PQP . Assert . asDefined ( args [ 1 ] ) ) ; const columnGenerator = TypeUtils . assertAsFunction ( PQP . Assert . asDefined ( args [ 2 ] ) ) ; const maybeColumnType = args . length === 4 ? TypeUtils . assertAsType ( PQP . Assert . asDefined ( args [ 3 ] ) ) : undefined ; if ( ! TypeUtils . isTextLiteral ( columnName ) ) { return undefined ; } let columnType ; if ( maybeColumnType !== undefined ) { columnType = maybeColumnType ; } else if ( TypeUtils . isDefinedFunction ( columnGenerator ) ) { columnType = columnGenerator . returnType ; } else { columnType = Type . AnyInstance ; } const normalizedColumnName = PQP . Language . TextUtils . normalizeIdentifier ( columnName . literal . slice ( 1 , - 1 ) ) ; if ( TypeUtils . isDefinedTable ( table ) ) { if ( table . fields . has ( normalizedColumnName ) ) { return Type . NoneInstance ; } return TypeUtils . createDefinedTable ( table . isNullable , new PQP . OrderedMap ( [ ... table . fields . entries ( ) , [ normalizedColumnName , columnType ] ] ) , table . isOpen ) ; } else { return TypeUtils . createDefinedTable ( table . isNullable , new PQP . OrderedMap ( [ [ normalizedColumnName , columnType ] ] ) , true ) ; } } const SmartTypeResolverFns = new Map ( [ [ "(table: table, newColumnName: text, columnGenerator: function, columnType: optional nullable type) => table" , resolveTableAddColumn , ] , ] ) ;