import * as fse from 'fs-extra' ; import * as path from "path" ; import { assetsPath } from '../../../common' ; import { ExpressionType } from '../../documents/templates/ExpressionType' ; import { FunctionBehaviors , IFunctionMetadata , IFunctionParameterMetadata } from '../../documents/templates/IFunctionMetadata' ; import { assert } from '../../fixed_assert' ; import { IUsageInfo } from '../../vscodeIntegration/UsageInfoHoverInfo' ; import { DefinitionKind , INamedDefinition } from '../INamedDefinition' ; import { StringValue } from '../json/JSON' ; export function isBuiltinFunctionDefinition ( definition ) { return definition . definitionKind === DefinitionKind . BuiltinFunction ; } /**
 * An accessor class for the Azure RM storage account.
 */ export class AzureRMAssets { private static _functionsMetadata : FunctionsMetadata | undefined ; public static setFunctionsMetadata ( metadataString ) { if ( ! metadataString ) { AzureRMAssets . _functionsMetadata = undefined ; } else { let array = BuiltinFunctionMetadata . fromString ( metadataString ) ; AzureRMAssets . _functionsMetadata = new FunctionsMetadata ( array ) ; } } public static getFunctionsMetadata ( ) { if ( ! AzureRMAssets . _functionsMetadata ) { let uri = AzureRMAssets . getFunctionMetadataUri ( ) ; let contents = AzureRMAssets . readFile ( uri ) ; let array = BuiltinFunctionMetadata . fromString ( contents ) ; AzureRMAssets . _functionsMetadata = new FunctionsMetadata ( array ) ; } return AzureRMAssets . _functionsMetadata ; } public static getFunctionMetadataFromName ( functionName ) { return this . getFunctionsMetadata ( ) . findbyName ( functionName ) ; } public static getFunctionMetadataFromPrefix ( functionNamePrefix ) { return this . getFunctionsMetadata ( ) . filterByPrefix ( functionNamePrefix ) ; } /**
     * Get the URI to the file where the function metadata is stored.
     */ private static getFunctionMetadataUri ( ) { return AzureRMAssets . getLocalAssetUri ( "ExpressionMetadata.json" ) ; } private static getLocalAssetUri ( assetFileName ) { return path . join ( assetsPath , assetFileName ) ; } private static readFile ( filePath ) { return fse . readFileSync ( filePath , "utf8" ) ; } } /**
 * Metadata for all TLE (Template Language Expression) functions.
 */ export class FunctionsMetadata { public constructor ( public readonly functionMetadata ) { } public findbyName ( functionName ) { const lowerCasedFunctionName = functionName . toLowerCase ( ) ; return this . functionMetadata . find ( func => func . lowerCaseName === lowerCasedFunctionName ) ; } public filterByPrefix ( functionNamePrefix ) { const lowerCasedPrefix = functionNamePrefix . toLowerCase ( ) ; return this . functionMetadata . filter ( func => func . lowerCaseName . startsWith ( lowerCasedPrefix ) ) ; } } /**
 * Metadata for a TLE (Template Language Expression) function.
 */ export class BuiltinFunctionMetadata implements IFunctionMetadata , INamedDefinition { public readonly nameValue : StringValue | undefined = undefined ; public definitionKind : DefinitionKind = DefinitionKind . BuiltinFunction ; private readonly _name : string ; private readonly _lowerCaseName : string ; private readonly _returnType : ExpressionType | undefined ; constructor ( name , private readonly _usage , private readonly _description , private readonly _minimumArguments , private readonly _maximumArguments , private readonly _returnValueMembers , private readonly _behaviors ) { assert ( _maximumArguments !== null , "Use undefined, not null" ) ; this . _name = name || '' ; this . _lowerCaseName = this . _name . toLowerCase ( ) ; this . _returnType = this . returnValueMembers . length > 0 ? 'object' : undefined ; } public get fullName ( ) : string { return this . _name ; } public get unqualifiedName ( ) : string { return this . _name ; } public get lowerCaseName ( ) : string { return this . _lowerCaseName ; } public get usage ( ) : string { return this . returnType ? `${ this . _usage } [${ this . returnType }]` : this . _usage ; } public get usageInfo ( ) : IUsageInfo { return { usage : this . usage , friendlyType : "function" , description : this . description } ; } public get parameters ( ) : IFunctionParameterMetadata [ ] { const usage = this . usage ; const leftParenthesisIndex = usage . indexOf ( "(" ) ; const rightParenthesisIndex = usage . indexOf ( ")" ) ; const parametersSubstring = usage . substr ( leftParenthesisIndex + 1 , rightParenthesisIndex - leftParenthesisIndex - 1 ) ; const result = [ ] ; if ( parametersSubstring ) { for ( const parameter of parametersSubstring . split ( "," ) ) { result . push ( { name : parameter . trim ( ) , type : undefined } ) ; } } return result ; } public get description ( ) : string { return this . _description ; } public get minimumArguments ( ) : number { return this . _minimumArguments ; } public get maximumArguments ( ) : number | undefined { return this . _maximumArguments ; } public get returnType ( ) : ExpressionType | undefined { return this . _returnType ; } public get returnValueMembers ( ) : string [ ] { return this . _returnValueMembers ; } public hasBehavior ( behavior ) { return ! ! this . _behaviors && this . _behaviors . includes ( behavior ) ; } public static fromString ( metadataString ) { let metadataJSON ; try { metadataJSON = < FunctionMetadataContract > JSON . parse ( metadataString ) ; } catch ( e ) { metadataJSON = { functionSignatures : [ ] } ; } return BuiltinFunctionMetadata . fromJSON ( metadataJSON ) ; } public static fromJSON ( metadataJSON ) { const result = [ ] ; if ( metadataJSON && metadataJSON . functionSignatures ) { for ( const functionMetadata of metadataJSON . functionSignatures ) { if ( functionMetadata ) { const returnValueMembers = [ ] ; if ( functionMetadata . returnValueMembers ) { for ( const returnValueMember of functionMetadata . returnValueMembers ) { returnValueMembers . push ( returnValueMember . name ) ; } } returnValueMembers . sort ( ) ; result . push ( new BuiltinFunctionMetadata ( functionMetadata . name , functionMetadata . expectedUsage , functionMetadata . description , functionMetadata . minimumArguments , functionMetadata . maximumArguments ?? undefined , returnValueMembers , functionMetadata . behaviors ) ) ; } } } return result ; } } interface FunctionMetadataContract { functionSignatures : { name : string ; expectedUsage : string ; description : string ; minimumArguments : number ; maximumArguments : number | null ; returnValueMembers ? : { name : string ; } [ ] ; behaviors : FunctionBehaviors [ ] | null ; } [ ] ; }