Skip to content
Open
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 @@ -380,7 +380,7 @@ private ValueExpression GetResultConversion(ClientResponseApi result, HttpRespon
}
else
{
return response.Content().ToObjectFromJson(responseBodyType.OutputType);
return ModelReaderWriterSnippets.Read(response.Content(), responseBodyType.OutputType);
}
}
if (responseBodyType.IsDictionary)
Expand All @@ -391,7 +391,7 @@ private ValueExpression GetResultConversion(ClientResponseApi result, HttpRespon
}
else
{
return response.Content().ToObjectFromJson(responseBodyType.OutputType);
return ModelReaderWriterSnippets.Read(response.Content(), responseBodyType.OutputType);
}
}
if (responseBodyType.Equals(typeof(string)) && ServiceMethod.Operation.Responses.Any(r => r.IsErrorResponse is false && r.ContentTypes.Contains("text/plain")))
Expand All @@ -400,11 +400,11 @@ private ValueExpression GetResultConversion(ClientResponseApi result, HttpRespon
}
if (responseBodyType.IsFrameworkType)
{
return response.Content().ToObjectFromJson(responseBodyType);
return ModelReaderWriterSnippets.Read(response.Content(), responseBodyType);
}
if (responseBodyType.IsEnum)
{
return responseBodyType.ToEnum(response.Content().ToObjectFromJson(responseBodyType.UnderlyingEnumType));
return responseBodyType.ToEnum(ModelReaderWriterSnippets.Read(response.Content(), responseBodyType.UnderlyingEnumType));
}
return result.CastTo(responseBodyType);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.ClientModel;
using System.ClientModel.Primitives;
using Microsoft.TypeSpec.Generator.Expressions;
using Microsoft.TypeSpec.Generator.Primitives;
using static Microsoft.TypeSpec.Generator.Snippets.Snippet;

namespace Microsoft.TypeSpec.Generator.ClientModel.Snippets
{
internal static class ModelReaderWriterSnippets
{
public static InvokeMethodExpression Read(ValueExpression data, CSharpType type)
{
return Static(typeof(ModelReaderWriter)).Invoke(
nameof(ModelReaderWriter.Read),
[data, ModelSerializationExtensionsSnippets.Wire, ModelReaderWriterContextSnippets.Default],
new CSharpType[] { type });
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1133,5 +1133,66 @@ await MockHelpers.LoadMockGeneratorAsync(
Assert.IsNotNull(collectionResultDefinition, "CollectionResultDefinition should be added even when paging methods are customized");
}

[TestCase("ListOfStrings", typeof(IReadOnlyList<string>))]
[TestCase("DictionaryOfInts", typeof(IReadOnlyDictionary<string, int>))]
[TestCase("Int32", typeof(int))]
[TestCase("Enum", typeof(int))] // Enum is tested with underlying type
public void AotCompatibleModelReaderWriterReadMethods(string testCaseName, Type returnType)
{
InputType? inputType = null;
bool isEnum = testCaseName == "Enum";

if (testCaseName == "ListOfStrings")
{
inputType = InputFactory.Array(InputPrimitiveType.String);
}
else if (testCaseName == "DictionaryOfInts")
{
inputType = InputFactory.Dictionary(InputPrimitiveType.Int32);
}
else if (testCaseName == "Int32")
{
inputType = InputPrimitiveType.Int32;
}
else if (isEnum)
{
inputType = InputFactory.Int32Enum("TestEnum", [("Value1", 1), ("Value2", 2)]);
}

var inputOperation = InputFactory.Operation(
"GetData",
responses: [InputFactory.OperationResponse([200], inputType!)]);

var inputServiceMethod = InputFactory.BasicServiceMethod("GetData", inputOperation);
var inputClient = InputFactory.Client("TestClient", methods: [inputServiceMethod]);

MockHelpers.LoadMockGenerator();
var client = ScmCodeModelGenerator.Instance.TypeFactory.CreateClient(inputClient);

var methodCollection = new ScmMethodProviderCollection(inputServiceMethod, client!);
Assert.IsNotNull(methodCollection);

var convenienceMethod = methodCollection.FirstOrDefault(m
=> m.Signature.Parameters.All(p => p.Name != "options")
&& m.Signature.Name == $"{inputOperation.Name.ToIdentifierName()}");

Assert.IsNotNull(convenienceMethod);

// Verify the body uses ModelReaderWriter.Read with context parameter
var bodyText = convenienceMethod!.BodyStatements!.ToDisplayString();

StringAssert.Contains("ModelReaderWriter.Read", bodyText,
"Method should use ModelReaderWriter.Read for AOT compatibility");
StringAssert.Contains("SampleContext.Default", bodyText,
"Method should include ModelReaderWriterContext.Default parameter");
StringAssert.Contains("ModelSerializationExtensions.WireOptions", bodyText,
"Method should include WireOptions parameter");

// Compare with expected output (normalize line endings for cross-platform compatibility)
var expected = Helpers.GetExpectedFromFile(testCaseName).Replace("\r\n", "\n");
var actual = bodyText.Replace("\r\n", "\n");
Assert.AreEqual(expected, actual);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetData(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<global::System.Collections.Generic.IReadOnlyDictionary<string, int>>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetData(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<int>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default).ToTestEnum(), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetData(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<int>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetData(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<global::System.Collections.Generic.IReadOnlyList<string>>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetScalar(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson<bool>(), result.GetRawResponse());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<bool>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetScalar(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson<global::System.DateTimeOffset>(), result.GetRawResponse());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<global::System.DateTimeOffset>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetScalar(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson<double>(), result.GetRawResponse());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<double>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetScalar(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson<int>(), result.GetRawResponse());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<int>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetScalar(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson<long>(), result.GetRawResponse());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<long>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetScalar(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson<float>(), result.GetRawResponse());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<float>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetScalar(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson<string>(), result.GetRawResponse());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<string>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
global::System.ClientModel.ClientResult result = this.GetScalar(cancellationToken.ToRequestOptions());
return global::System.ClientModel.ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson<global::System.TimeSpan>(), result.GetRawResponse());
return global::System.ClientModel.ClientResult.FromValue(global::System.ClientModel.Primitives.ModelReaderWriter.Read<global::System.TimeSpan>(result.GetRawResponse().Content, global::Sample.ModelSerializationExtensions.WireOptions, global::Sample.SampleContext.Default), result.GetRawResponse());
Loading