import * as PQLS from "@microsoft/powerquery-language-services" ; import * as PQP from "@microsoft/powerquery-parser" ; import { CompletionItemKind } from "@microsoft/powerquery-language-services" ; import * as StandardLibraryEnUs from "./bylocalization/enUs.json" ; import { StandardLibrary , StandardLibraryExport , StandardLibraryFunctionParameter } from "./standardLibrary" ; import { createStandardLibraryTypeResolver } from "./standardLibraryTypeResolver" ; export function getOrCreateStandardLibrary ( locale ? ) { locale = locale ?? PQP . Locale . en_US ; if ( ! libraryByLocale . has ( locale ) ) { const libraryDefinitions = getOrCreateStandardLibraryDefinitions ( locale ) ; libraryByLocale . set ( locale , { externalTypeResolver : createStandardLibraryTypeResolver ( libraryDefinitions ) , libraryDefinitions , } ) ; } return PQP . Assert . asDefined ( libraryByLocale . get ( locale ) ) ; } function getOrCreateStandardLibraryDefinitions ( locale ) { if ( ! libraryDefinitionsByLocale . has ( locale ) ) { const json = jsonByLocale . get ( locale ) ?? StandardLibraryEnUs ; const mapped = new Map ( json . map ( ( xport ) => [ xport . name , mapExport ( xport ) ] ) ) ; libraryDefinitionsByLocale . set ( locale , mapped ) ; } return PQP . Assert . asDefined ( libraryDefinitionsByLocale . get ( locale ) ) ; } const jsonByLocale = new Map ( [ [ PQP . Locale . en_US , StandardLibraryEnUs ] ] ) ; const libraryByLocale = new Map ( ) ; const libraryDefinitionsByLocale = new Map ( ) ; function mapExport ( xport ) { const primitiveType = assertPrimitiveTypeFromString ( xport . dataType ) ; const label = xport . name ; const description = xport . documentation ?. description ?? "No description available" ; if ( primitiveType . kind === PQP . Language . Type . TypeKind . Type ) { return { kind : PQLS . Library . LibraryDefinitionKind . Type , label , description , asPowerQueryType : primitiveType , completionItemKind : assertGetCompletionItemKind ( xport . completionItemType ) , } ; } else if ( xport . functionParameters ) { const asPowerQueryType = mapLibraryFunctionSignatureToType ( xport , primitiveType ) ; return { kind : PQLS . Library . LibraryDefinitionKind . Function , label : PQP . Language . TypeUtils . nameOf ( asPowerQueryType ) , description , asPowerQueryType , completionItemKind : assertGetCompletionItemKind ( xport . completionItemType ) , parameters : xport . functionParameters . map ( mapParameterToLibraryParameter ) , } ; } else { return { kind : PQLS . Library . LibraryDefinitionKind . Constant , label , description , asPowerQueryType : primitiveType , completionItemKind : assertGetCompletionItemKind ( xport . completionItemType ) , } ; } } function mapLibraryFunctionSignatureToType ( xport , returnType ) { const xportParameters = xport . functionParameters ?? [ ] ; return PQP . Language . TypeUtils . createDefinedFunction ( false , xportParameters . map ( ( parameter ) => { const primitiveType = assertPrimitiveTypeFromString ( parameter . parameterType ) ; return { isNullable : primitiveType . isNullable , isOptional : ! parameter . isRequired , maybeType : primitiveType . kind , nameLiteral : parameter . name , } ; } ) , returnType ) ; } function mapParameterToLibraryParameter ( parameter ) { const primitiveType = assertPrimitiveTypeFromString ( parameter . parameterType ) ; return { isNullable : primitiveType . isNullable , isOptional : false , label : parameter . name , maybeDocumentation : parameter . description ?? undefined , typeKind : primitiveType . kind , } ; } function assertGetTypeKind ( text ) { if ( ! PQP . Language . ConstantUtils . isPrimitiveTypeConstant ( text ) ) { throw new Error ( `unknown type: ${ text }` ) ; } return PQP . Language . TypeUtils . typeKindFromPrimitiveTypeConstantKind ( text ) ; } function assertGetCompletionItemKind ( variant ) { switch ( variant ) { case CompletionItemKind . Constant : case CompletionItemKind . Constructor : case CompletionItemKind . Enum : case CompletionItemKind . EnumMember : case CompletionItemKind . Event : case CompletionItemKind . Field : case CompletionItemKind . File : case CompletionItemKind . Folder : case CompletionItemKind . Function : case CompletionItemKind . Interface : case CompletionItemKind . Keyword : case CompletionItemKind . Method : case CompletionItemKind . Module : case CompletionItemKind . Operator : case CompletionItemKind . Property : case CompletionItemKind . Reference : case CompletionItemKind . Snippet : case CompletionItemKind . Struct : case CompletionItemKind . Text : case CompletionItemKind . TypeParameter : case CompletionItemKind . Unit : case CompletionItemKind . Value : case CompletionItemKind . Variable : return variant ; default : throw new PQP . CommonError . InvariantError ( `unknown CompletionItemKind variant value` , { variant } ) ; } } function assertPrimitiveTypeFromString ( text ) { const split = text . split ( " " ) ; let isNullable ; let typeKind ; switch ( split . length ) { case 0 : throw new Error ( "expected parameter.type to be nullish" ) ; case 1 : { isNullable = false ; typeKind = assertGetTypeKind ( text ) ; break ; } case 2 : { if ( split [ 0 ] !== PQP . Language . Constant . LanguageConstant . Nullable ) { throw new Error ( `expected first word in text to be ${ PQP . Language . Constant . LanguageConstant . Nullable }` ) ; } isNullable = true ; typeKind = assertGetTypeKind ( split [ 1 ] ) ; break ; } default : throw new Error ( "expected text to be 1 or 2 words" ) ; } return PQP . Language . TypeUtils . createPrimitiveType ( isNullable , typeKind ) ; }