import { templateKeys } from '../../../common' ; import { assert } from '../../fixed_assert' ; import { DefinitionKind , INamedDefinition } from '../../language/INamedDefinition' ; import * as Json from "../../language/json/JSON" ; import { Span } from '../../language/Span' ; import { CachedValue } from '../../util/CachedValue' ; import { mapJsonObjectValue } from '../../util/mapJsonObjectValue' ; import { IUsageInfo } from '../../vscodeIntegration/UsageInfoHoverInfo' ; /**
 * This represents the definition of a top-level parameter in a deployment template.
 */ export interface IVariableDefinition extends INamedDefinition { nameValue : Json . StringValue ; value : Json . Value | undefined ; span : Span ; usageInfo : IUsageInfo ; } export function isVariableDefinition ( definition ) { return definition . definitionKind === DefinitionKind . Variable ; } abstract class VariableDefinition implements IVariableDefinition { public readonly definitionKind : DefinitionKind = DefinitionKind . Variable ; public abstract nameValue : Json . StringValue ; public abstract value : Json . Value | undefined ; public abstract span : Span ; public abstract usageInfo : IUsageInfo ; } export class TopLevelVariableDefinition extends VariableDefinition { private readonly _value : CachedValue < Json . Value | undefined > = new CachedValue < Json . Value | undefined > ( ) ; constructor ( private readonly _property ) { super ( ) ; assert ( _property ) ; } public get nameValue ( ) : Json . StringValue { return this . _property . nameValue ; } public get value ( ) : Json . Value | undefined { return this . _value . getOrCacheValue ( ( ) => { const value = this . _property . value ; const valueObject = Json . asObjectValue ( value ) ; if ( valueObject ) { return this . expandCopyBlocks ( valueObject ) ; } else { return value ; } } ) ; } public get span ( ) : Span { return this . _property . span ; } public get usageInfo ( ) : IUsageInfo { return { usage : this . nameValue . unquotedValue , friendlyType : "variable" , description : undefined } ; } /**
     * Convenient way of seeing what this object represents in the debugger, shouldn't be used for production code
     */ public get __debugDisplay ( ) : string { return `${ this . nameValue . toString ( ) } (var)` ; } private expandCopyBlocks ( value ) { const valueAsObject = Json . asObjectValue ( value ) ; if ( ! valueAsObject ) { return value ; } return mapJsonObjectValue ( valueAsObject , prop => { const arrayValue = Json . asArrayValue ( prop . value ) ; if ( ! ! arrayValue && prop . nameValue . unquotedValue . toLowerCase ( ) === templateKeys . copyLoop ) { const loopVarProperties = [ ] ; for ( let copyElement of arrayValue . elements ) { const loopVarObject = Json . asObjectValue ( copyElement ) ; if ( loopVarObject ) { const name = Json . asStringValue ( loopVarObject . getPropertyValue ( templateKeys . copyName ) ) ; const input = loopVarObject . getPropertyValue ( templateKeys . copyInput ) ; const count = loopVarObject . getPropertyValue ( templateKeys . copyCount ) ; if ( name && count && input ) { const array = new Json . ArrayValue ( input . span , [ input ] ) ; const loopValueProperty = new Json . Property ( input . span , name , array ) ; loopVarProperties . push ( loopValueProperty ) ; } } } return loopVarProperties ; } else { const processedValue = this . expandCopyBlocks ( prop . value ) ; if ( processedValue !== prop . value ) { return new Json . Property ( prop . span , prop . nameValue , processedValue ) ; } return prop ; } } ) ; } } /**
 * This class represents the definition of a top-level parameter in a deployment template.
 */ export class TopLevelCopyBlockVariableDefinition extends VariableDefinition { public readonly value : Json . Value | undefined ; public constructor ( /**
     * The "copy" block array element corresponding to this variable (see below)
     */ private readonly _copyVariableObject , /**
     * StringValue representing the "name" property of the copy block
     */ public readonly nameValue , /**
     * The "input" property from the copy block, represents the value of each instance of the
     * resulting variable array
     */ input ) { super ( ) ; this . value = input ? new Json . ArrayValue ( input . span , [ input ] ) : undefined ; } public static createIfValid ( copyVariableObject ) { const asObject = Json . asObjectValue ( copyVariableObject ) ; if ( asObject ) { const nameValue = Json . asStringValue ( asObject . getPropertyValue ( templateKeys . copyName ) ) ; if ( nameValue ) { const value = asObject . getPropertyValue ( templateKeys . copyInput ) ; return new TopLevelCopyBlockVariableDefinition ( asObject , nameValue , value ) ; } } return undefined ; } public get span ( ) : Span { return this . _copyVariableObject . span ; } public get usageInfo ( ) : IUsageInfo { return { usage : this . nameValue . unquotedValue , friendlyType : "iteration variable" , description : undefined } ; } /**
     * Convenient way of seeing what this object represents in the debugger, shouldn't be used for production code
     */ public get __debugDisplay ( ) : string { return `${ this . nameValue . toString ( ) } (iter var)` ; } }