Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -658,9 +658,11 @@ private MethodBodyStatement[] BuildPrimaryConstructorBody(IReadOnlyList<Paramete
if (_endpointParameter.Type.Equals(typeof(string)))
{
var serverTemplate = _inputEndpointParam!.ServerUrlTemplate;
// Build the URI by converting the named placeholders to indexed placeholders and collecting arguments
var (convertedTemplate, templateArgs) = ConvertUriTemplateToFormattableString(serverTemplate!, primaryConstructorParameters);
endpointAssignment = EndpointField.Assign(
New.Instance(typeof(Uri),
new FormattableStringExpression(serverTemplate!, [_endpointParameter])));
new FormattableStringExpression(convertedTemplate, templateArgs)));
}
else
{
Expand Down Expand Up @@ -1005,6 +1007,87 @@ private ParameterProvider BuildClientEndpointParameter()
};
}

/// Converts a URI template with named placeholders like "{Endpoint}/anomalydetector/{ApiVersion}"
/// to a formattable string format with indexed placeholders like "{0}/anomalydetector/{1}"
/// and returns the corresponding arguments.
private (string Template, List<ValueExpression> Args) ConvertUriTemplateToFormattableString(
string uriTemplate,
IReadOnlyList<ParameterProvider> parameters)
{
// Build a lookup for parameters by name (case-insensitive)
var paramsByName = new Dictionary<string, ParameterProvider>(StringComparer.OrdinalIgnoreCase);
foreach (var param in parameters)
{
paramsByName[param.Name] = param;
}

// Also add the endpoint parameter explicitly (it may have a different name)
if (!paramsByName.ContainsKey(_endpointParameter.Name))
{
paramsByName[_endpointParameter.Name] = _endpointParameter;
}

// Also add fields from _additionalClientFields
foreach (var field in _additionalClientFields.Value)
{
// Field names are like "_apiVersion", parameter names are like "ApiVersion"
var paramName = field.Name.TrimStart('_');
if (!paramsByName.ContainsKey(paramName))
{
paramsByName[paramName] = field.AsParameter;
}
}

var args = new List<ValueExpression>();
var result = new System.Text.StringBuilder();
var templateSpan = uriTemplate.AsSpan();

while (templateSpan.Length > 0)
{
var openBrace = templateSpan.IndexOf('{');
if (openBrace < 0)
{
// No more placeholders, append the rest
result.Append(templateSpan);
break;
}

// Append literal part before the placeholder
result.Append(templateSpan.Slice(0, openBrace));
templateSpan = templateSpan.Slice(openBrace + 1);

var closeBrace = templateSpan.IndexOf('}');
if (closeBrace < 0)
{
// Malformed template, append remaining as-is
result.Append('{');
result.Append(templateSpan);
break;
}

var paramName = templateSpan.Slice(0, closeBrace).ToString();
templateSpan = templateSpan.Slice(closeBrace + 1);

// Find the corresponding parameter or field
if (paramsByName.TryGetValue(paramName, out var param))
{
result.Append('{');
result.Append(args.Count);
result.Append('}');
args.Add(param.Field ?? (ValueExpression)param);
}
else
{
// Parameter not found - this is a configuration error
throw new InvalidOperationException(
$"URI template placeholder '{{{paramName}}}' in '{uriTemplate}' could not be resolved. " +
$"Available parameters: {string.Join(", ", paramsByName.Keys)}");
}
}

return (result.ToString(), args);
}

private IReadOnlyList<ClientProvider> GetSubClients()
{
var subClients = new List<ClientProvider>(_inputClient.Children.Count);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,10 @@ private MethodBodyStatements BuildMessage(
var operation = serviceMethod.Operation;
var classifier = GetClassifier(operation);

var paramMap = new Dictionary<string, ParameterProvider>(signature.Parameters.ToDictionary(p => p.Name));
var paramMap = new Dictionary<string, ParameterProvider>(signature.Parameters.ToDictionary(p => p.WireInfo.SerializedName));
foreach (var param in ClientProvider.ClientParameters)
{
paramMap[param.Name] = param;
paramMap[param.WireInfo.SerializedName] = param;
}

InputPagingServiceMethod? pagingServiceMethod = serviceMethod as InputPagingServiceMethod;
Expand Down Expand Up @@ -282,9 +282,9 @@ private Dictionary<string, ParameterProvider> GetReinjectedParametersMap(
foreach (var param in nextLink.ReInjectedParameters)
{
var reinjectedParameter = ScmCodeModelGenerator.Instance.TypeFactory.CreateParameter(param);
if (reinjectedParameter != null && paramMap.TryGetValue(reinjectedParameter.Name, out var paramInSignature))
if (reinjectedParameter != null && paramMap.TryGetValue(reinjectedParameter.WireInfo.SerializedName, out var paramInSignature))
{
reinjectedParamsMap[param.Name] = paramInSignature;
reinjectedParamsMap[param.SerializedName] = paramInSignature;
}
}
}
Expand All @@ -298,9 +298,9 @@ private Dictionary<string, ParameterProvider> GetReinjectedParametersMap(
if (pageSizeParameter != null)
{
var pageSizeParam = ScmCodeModelGenerator.Instance.TypeFactory.CreateParameter(pageSizeParameter);
if (pageSizeParam != null && paramMap.TryGetValue(pageSizeParam.Name, out var paramInSignature))
if (pageSizeParam != null && paramMap.TryGetValue(pageSizeParam.WireInfo.SerializedName, out var paramInSignature))
{
reinjectedParamsMap[pageSizeParameter.Name] = paramInSignature;
reinjectedParamsMap[pageSizeParameter.SerializedName] = paramInSignature;
}
}
}
Expand Down Expand Up @@ -648,36 +648,29 @@ private void AddUriSegments(
/* when the parameter is in operation.uri, it is client parameter
* It is not operation parameter and not in inputParamHash list.
*/
var isClientParameter = ClientProvider.ClientParameters.Any(p => p.Name == paramName);
var clientParam = ClientProvider.ClientParameters.FirstOrDefault(p => p.WireInfo.SerializedName == paramName);
CSharpType? type;
SerializationFormat? serializationFormat;
ValueExpression? valueExpression;
InputParameter? inputParam = null;
if (isClientParameter)
if (clientParam != null)
{
GetParamInfo(paramMap[paramName], out type, out serializationFormat, out valueExpression);
GetParamInfo(clientParam, out type, out serializationFormat, out valueExpression);
}
else
{
if (isClientParameter)
inputParam = inputParamMap[paramName];
if (inputParam is InputPathParameter || inputParam is InputEndpointParameter)
{
GetParamInfo(paramMap[paramName], out type, out serializationFormat, out valueExpression);
GetParamInfo(paramMap, operation, inputParam, out type, out serializationFormat, out valueExpression);
if (valueExpression == null)
{
break;
}
}
else
{
inputParam = inputParamMap[paramName];
if (inputParam is InputPathParameter || inputParam is InputEndpointParameter)
{
GetParamInfo(paramMap, operation, inputParam, out type, out serializationFormat, out valueExpression);
if (valueExpression == null)
{
break;
}
}
else
{
throw new InvalidOperationException($"The location of parameter {inputParam.Name} should be path or uri");
}
throw new InvalidOperationException($"The location of parameter {inputParam.SerializedName} should be path or uri");
}
}
string? format = serializationFormat?.ToFormatSpecifier();
Expand Down Expand Up @@ -738,7 +731,7 @@ private static void GetParamInfo(Dictionary<string, ParameterProvider> paramMap,
}
else
{
if (paramMap.TryGetValue(inputParam.Name, out var paramProvider))
if (paramMap.TryGetValue(inputParam.SerializedName, out var paramProvider))
{
GetParamInfo(paramProvider, out type, out serializationFormat, out valueExpression);
}
Expand Down
Loading