private static void BuildContextualParameterMappingHierarchy()

in src/AutoRest.CSharp/Mgmt/Decorator/ParameterMappingBuilder.cs [41:152]


        private static void BuildContextualParameterMappingHierarchy(RequestPath current, Stack<ContextualParameterMapping> parameterMappingStack, FormattableString idVariableName, string invocationSuffix = "")
        {
            // Check if the current path is a scope parameter
            if (current.IsRawParameterizedScope())
            {
                // in this case, we should only have one segment in this current path
                parameterMappingStack.Push(new ContextualParameterMapping(string.Empty, current.Last(), $"{idVariableName}{invocationSuffix}"));
                return;
            }
            // RequestPath of tenant does not have any parameter in it (actually it does not have anything), we take this as an exit
            if (current == RequestPath.Tenant)
                return;
            var parent = current.ParentRequestPath();
            // Subscription and ManagementGroup are not terminal states - tenant is their parent
            if (current == RequestPath.Subscription)
            {
                // using the reference name of the last segment as the parameter name, aka, subscriptionId
                parameterMappingStack.Push(new ContextualParameterMapping(current.SkipLast(1).Last().ConstantValue, current.Last(), $"{idVariableName}.SubscriptionId"));
            }
            else if (current == RequestPath.ManagementGroup)
            {
                // using the reference name of the last segment as the parameter name, aka, groupId
                parameterMappingStack.Push(new ContextualParameterMapping(current.SkipLast(1).Last().ConstantValue, current.Last(), $"{idVariableName}{invocationSuffix}.Name"));
            }
            // ResourceGroup is not terminal state - Subscription is its parent
            else if (current == RequestPath.ResourceGroup)
            {
                // using the reference name of the last segment as the parameter name, aka, resourceGroupName
                parameterMappingStack.Push(new ContextualParameterMapping(current.SkipLast(1).Last().ConstantValue, current.Last(), $"{idVariableName}.ResourceGroupName"));
            }
            // this branch is for every other cases - all the request path that corresponds to a resource in this swagger
            else
            {
                // get the diff between current and parent
                var diffPath = parent.TrimAncestorFrom(current);
                // get the segment in pairs
                var segmentPairs = SplitDiffIntoPairs(diffPath).ToList();
                var indexOfProvidersPair = segmentPairs.FindIndex(pair => pair[0] == Segment.Providers);
                var resourceTypeIdVariableName = idVariableName;
                // from the tail, check these segments in pairs
                for (int i = 0; i < segmentPairs.Count; i++)
                {
                    var pair = segmentPairs[i];
                    if (pair.Count == 2)
                    {
                        // we have a pair of segment, therefore here pair[0] will always be the key, `resourceGroups` for instance.
                        // The key can also be variable in some scenarios
                        // pair[1] will always be the value, which is Id.Name or Id.Namespace (if its key is providers)
                        var keySegment = pair[0];
                        var valueSegment = pair[1];
                        var appendParent = false;
                        if (valueSegment.IsReference)
                        {
                            if (keySegment == Segment.Providers) // if the key is providers and the value is a parameter
                            {
                                if (current.Count <= 4) // path is /providers/{resourceProviderNamespace} or /subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}
                                {
                                    parameterMappingStack.Push(new ContextualParameterMapping(keySegment.ConstantValue, valueSegment, $"{idVariableName}.Provider"));
                                }
                                else
                                {
                                    parameterMappingStack.Push(new ContextualParameterMapping(keySegment.ConstantValue, valueSegment, $"{resourceTypeIdVariableName}.ResourceType.Namespace"));
                                }
                                // do not append a new .Parent to the id
                            }
                            else // for all other normal keys
                            {
                                parameterMappingStack.Push(new ContextualParameterMapping(keySegment.IsConstant ? keySegment.ConstantValue : string.Empty, valueSegment, $"{idVariableName}{invocationSuffix}.Name"));
                                appendParent = true;
                            }
                        }
                        else // in this branch pair[1] is a constant
                        {
                            if (keySegment != Segment.Providers)
                            {
                                // if the key is not providers, we need to skip this level and increment the parent hierarchy
                                appendParent = true;
                            }
                        }
                        if (keySegment.IsReference)
                        {
                            parameterMappingStack.Push(new ContextualParameterMapping(string.Empty, keySegment, $"{idVariableName}{invocationSuffix}.ResourceType.GetLastType()", new[] { "System.Linq" }));
                            resourceTypeIdVariableName = $"{idVariableName}{invocationSuffix}";
                            appendParent = true;
                        }
                        else if (keySegment.IsExpandable)
                        {
                            //this is the case where we have expanded the reference into its enumerations
                            var keyParam = keySegment.Type.Name.ToVariableName();
                            parameterMappingStack.Push(new ContextualParameterMapping(keyParam, keyParam, keySegment.Type, $"\"{keySegment.ConstantValue}\"", Enumerable.Empty<string>()));
                            appendParent = true;
                        }
                        // add .Parent suffix
                        if (appendParent)
                            invocationSuffix += ".Parent";
                    }
                    else
                    {
                        if (pair[0].IsReference && pair[0].SkipUrlEncoding)
                        {
                            // we never have a case that we need to get the substring that have a gap after the provider-namespace key pair, throw an exception when it happens
                            if (segmentPairs.Count - indexOfProvidersPair != 1)
                                throw new NotImplementedException("We have a gap between the substring to get and the provider-namespace key pair. We need to update SubstringAfterProviderNamespace function to make sure it can accept an index to adopt this");
                            // if we only have one segment in this group, it should always be a reference
                            parameterMappingStack.Push(new ContextualParameterMapping(string.Empty, pair[0], $"{idVariableName}{invocationSuffix}.SubstringAfterProviderNamespace()"));
                        }
                    }
                }
            }
            // recursively get the parameters of its parent
            BuildContextualParameterMappingHierarchy(parent, parameterMappingStack, idVariableName, invocationSuffix);
        }