Skip to content

Commit 3fec08a

Browse files
Do not use ref for patch property in structs (microsoft#8568)
fixes: microsoft#8567
1 parent 40d973a commit 3fec08a

5 files changed

Lines changed: 131 additions & 4 deletions

File tree

packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/src/Providers/ScmModelProvider.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,11 @@ protected override ConstructorProvider[] BuildConstructors()
168168
}
169169

170170
var experimentalAttribute = new AttributeStatement(typeof(ExperimentalAttribute), [Literal(ScmEvaluationTypeDiagnosticId)]);
171-
171+
FieldModifiers modifiers = DeclarationModifiers.HasFlag(TypeSignatureModifiers.Struct)
172+
? FieldModifiers.Private | FieldModifiers.ReadOnly
173+
: FieldModifiers.Private;
172174
return new FieldProvider(
173-
modifiers: FieldModifiers.Private,
175+
modifiers: modifiers,
174176
type: _jsonPatchFieldType,
175177
description: null,
176178
name: JsonPatchFieldName,
@@ -185,13 +187,14 @@ protected override ConstructorProvider[] BuildConstructors()
185187
return null;
186188
}
187189

190+
bool isRef = !DeclarationModifiers.HasFlag(TypeSignatureModifiers.Struct);
188191
return new PropertyProvider(
189192
description: null,
190193
modifiers: MethodSignatureModifiers.Public,
191194
type: _jsonPatchFieldType,
192195
name: JsonPatchPropertyName,
193-
isRef: true,
194-
body: new ExpressionPropertyBody(new VariableExpression(JsonPatchField.Type, JsonPatchField.Declaration, IsRef: true)),
196+
isRef: isRef,
197+
body: new ExpressionPropertyBody(new VariableExpression(JsonPatchField.Type, JsonPatchField.Declaration, IsRef: isRef)),
195198
attributes:
196199
[
197200
new AttributeStatement(typeof(EditorBrowsableAttribute), FrameworkEnumValue(EditorBrowsableState.Never)),

packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator.ClientModel/test/Providers/ScmModelProvider/ScmModelProviderTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using System.Linq;
6+
using System.Threading.Tasks;
67
using Microsoft.TypeSpec.Generator.Input;
78
using Microsoft.TypeSpec.Generator.Primitives;
89
using Microsoft.TypeSpec.Generator.Tests.Common;
@@ -299,5 +300,47 @@ public void TestDynamicDerivedModel()
299300

300301
Assert.AreEqual(Helpers.GetExpectedFromFile(), file.Content);
301302
}
303+
304+
[Test]
305+
public void TestStructDynamicModel()
306+
{
307+
var catModel = InputFactory.Model("cat", isDynamicModel: true, modelAsStruct: true, properties:
308+
[
309+
InputFactory.Property("meows", InputPrimitiveType.Boolean, isRequired: true)
310+
]);
311+
312+
MockHelpers.LoadMockGenerator(inputModels: () => [catModel]);
313+
var model = ScmCodeModelGenerator.Instance.TypeFactory.CreateModel(catModel) as ClientModel.Providers.ScmModelProvider;
314+
315+
Assert.IsNotNull(model);
316+
Assert.IsTrue(model!.HasDynamicModelSupport);
317+
318+
var writer = new TypeProviderWriter(model);
319+
var file = writer.Write();
320+
321+
Assert.AreEqual(Helpers.GetExpectedFromFile(), file.Content);
322+
}
323+
324+
[Test]
325+
public async Task TestCustomStructDynamicModel()
326+
{
327+
var catModel = InputFactory.Model("cat", isDynamicModel: true, properties:
328+
[
329+
InputFactory.Property("meows", InputPrimitiveType.Boolean, isRequired: true)
330+
]);
331+
332+
await MockHelpers.LoadMockGeneratorAsync(
333+
compilation: async () => await Helpers.GetCompilationFromDirectoryAsync(),
334+
inputModels: () => [catModel]);
335+
var model = ScmCodeModelGenerator.Instance.TypeFactory.CreateModel(catModel) as ClientModel.Providers.ScmModelProvider;
336+
337+
Assert.IsNotNull(model);
338+
Assert.IsTrue(model!.HasDynamicModelSupport);
339+
340+
var writer = new TypeProviderWriter(model);
341+
var file = writer.Write();
342+
343+
Assert.AreEqual(Helpers.GetExpectedFromFile(), file.Content);
344+
}
302345
}
303346
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// <auto-generated/>
2+
3+
#nullable disable
4+
5+
using System.ClientModel.Primitives;
6+
using System.ComponentModel;
7+
using System.Diagnostics.CodeAnalysis;
8+
9+
namespace Sample.Models
10+
{
11+
internal readonly partial struct Cat
12+
{
13+
[global::System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SCME0001")]
14+
private readonly global::System.ClientModel.Primitives.JsonPatch _patch;
15+
16+
public Cat(bool meows)
17+
{
18+
Meows = meows;
19+
}
20+
21+
#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
22+
internal Cat(bool meows, in global::System.ClientModel.Primitives.JsonPatch patch)
23+
{
24+
Meows = meows;
25+
_patch = patch;
26+
}
27+
#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
28+
29+
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)]
30+
[global::System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SCME0001")]
31+
public global::System.ClientModel.Primitives.JsonPatch Patch => _patch;
32+
33+
public bool Meows { get; }
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.ClientModel.Primitives;
2+
using System.ComponentModel;
3+
using System.Diagnostics.CodeAnalysis;
4+
5+
namespace Sample.Models
6+
{
7+
[CodeGenType("Cat")]
8+
public partial readonly struct Cat
9+
{
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// <auto-generated/>
2+
3+
#nullable disable
4+
5+
using System.ClientModel.Primitives;
6+
using System.ComponentModel;
7+
using System.Diagnostics.CodeAnalysis;
8+
9+
namespace Sample.Models
10+
{
11+
public readonly partial struct Cat
12+
{
13+
[global::System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SCME0001")]
14+
private readonly global::System.ClientModel.Primitives.JsonPatch _patch;
15+
16+
public Cat(bool meows)
17+
{
18+
Meows = meows;
19+
}
20+
21+
#pragma warning disable SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
22+
internal Cat(bool meows, in global::System.ClientModel.Primitives.JsonPatch patch)
23+
{
24+
Meows = meows;
25+
_patch = patch;
26+
}
27+
#pragma warning restore SCME0001 // Type is for evaluation purposes only and is subject to change or removal in future updates.
28+
29+
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)]
30+
[global::System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SCME0001")]
31+
public global::System.ClientModel.Primitives.JsonPatch Patch => _patch;
32+
33+
public bool Meows { get; }
34+
}
35+
}

0 commit comments

Comments
 (0)