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);
}