private getPropertyAccessCompletions()

in src/documents/positionContexts/TemplatePositionContext.ts [593:665]


    private getPropertyAccessCompletions(tleValue: TLE.PropertyAccess, tleCharacterIndex: number, scope: TemplateScope): Completion.Item[] {
        const functionSource: TLE.FunctionCallValue | undefined = tleValue.functionSource;

        // Property accesses always start with a function call (might be 'variables'/'parameters')
        if (functionSource) {
            let propertyPrefix: string = "";
            let replaceSpan: Span = this.emptySpanAtDocumentCharacterIndex;
            const propertyNameToken: TLE.Token | undefined = tleValue.nameToken;
            if (propertyNameToken) {
                replaceSpan = propertyNameToken.span.translate(this.jsonTokenStartIndex);
                propertyPrefix = propertyNameToken.stringValue.substring(0, tleCharacterIndex - propertyNameToken.span.startIndex).toLowerCase();
            }

            const variableProperty: IVariableDefinition | undefined = scope.getVariableDefinitionFromFunctionCall(functionSource);
            const parameterProperty: IParameterDefinition | undefined = scope.getParameterDefinitionFromFunctionCall(functionSource);
            const sourcesNameStack: string[] = tleValue.sourcesNameStack;
            if (variableProperty) {
                // [variables('xxx').prop]

                // Is the variable's value is an object?
                const sourceVariableDefinition: Json.ObjectValue | undefined = Json.asObjectValue(variableProperty.value);
                if (sourceVariableDefinition) {
                    return this.getDeepPropertyAccessCompletions(
                        propertyPrefix,
                        sourceVariableDefinition,
                        sourcesNameStack,
                        replaceSpan);
                }
            } else if (parameterProperty) {
                // [parameters('xxx').prop]

                // Is the parameters's default valuean object?
                const parameterDefValue: Json.ObjectValue | undefined = parameterProperty.defaultValue ? Json.asObjectValue(parameterProperty.defaultValue) : undefined;
                if (parameterDefValue) {
                    const sourcePropertyDefinition: Json.ObjectValue | undefined = Json.asObjectValue(parameterDefValue.getPropertyValueFromStack(sourcesNameStack));
                    if (sourcePropertyDefinition) {
                        return this.getDeepPropertyAccessCompletions(
                            propertyPrefix,
                            sourcePropertyDefinition,
                            sourcesNameStack,
                            replaceSpan);
                    }
                }
            } else if (sourcesNameStack.length === 0) {
                // [function(...).prop]

                // We don't allow multiple levels of property access
                // (resourceGroup().prop1.prop2) on functions other than variables/parameters,
                // therefore checking that sourcesNameStack.length === 0
                const functionName: string | undefined = functionSource.name;

                // Don't currently support completions from a user function returning an object,
                // so there must be no function namespace
                if (functionName && !functionSource.namespaceToken) {
                    let functionMetadata: BuiltinFunctionMetadata | undefined = AzureRMAssets.getFunctionMetadataFromName(functionName);
                    if (functionMetadata) {
                        // Property completion off of a built-in function. Completions will consist of the
                        //   returnValueMembers of the function, if any.
                        const result: Completion.Item[] = [];
                        for (const returnValueMember of functionMetadata.returnValueMembers) {
                            if (propertyPrefix === "" || returnValueMember.toLowerCase().startsWith(propertyPrefix)) {
                                result.push(TemplatePositionContext.createPropertyCompletionItem(returnValueMember, replaceSpan));
                            }
                        }

                        return result;
                    }
                }
            }
        }

        return [];
    }