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 [];
}