Skip to content

Commit 9957c74

Browse files
authored
Add coverage for local polaymorphic types (Azure#49262)
* add coverage for local polaymorphic types * pr fb
1 parent df6e6fb commit 9957c74

22 files changed

+357
-183
lines changed

sdk/core/System.ClientModel/gen/Model/TypeBuilderSpec.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ internal sealed record TypeBuilderSpec
88
required public TypeRef Type { get; init; }
99
required public string Modifier { get; init; }
1010
required public TypeBuilderKind Kind { get; init; }
11+
required public TypeRef? PersistableModelProxy { get; init; }
1112
}

sdk/core/System.ClientModel/gen/ModelReaderWriterContextGenerator.Emitter.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,14 @@ private static void EmitPersistableModelInfo(
441441
builder.AppendLine(indent, $"protected override Type BuilderType => typeof({modelInfo.Type.Name});");
442442
builder.AppendLine();
443443

444-
builder.AppendLine(indent, $"protected override object CreateInstance() => new {modelInfo.Type.Name}();");
444+
if (modelInfo.PersistableModelProxy is not null)
445+
{
446+
builder.AppendLine(indent, $"protected override object CreateInstance() => new {modelInfo.PersistableModelProxy.Name}();");
447+
}
448+
else
449+
{
450+
builder.AppendLine(indent, $"protected override object CreateInstance() => new {modelInfo.Type.Name}();");
451+
}
445452

446453
indent--;
447454
builder.AppendLine(indent, "}");

sdk/core/System.ClientModel/gen/ModelReaderWriterContextGenerator.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,17 @@ private void ReportDiagnosticAndEmitSource(
186186
return null;
187187
}
188188

189+
var proxy = GetProxyType(typeSymbol);
190+
191+
if (typeSymbol.IsAbstract && proxy is null)
192+
return null; // Skip abstract types without a proxy
193+
189194
return new TypeBuilderSpec()
190195
{
191196
Modifier = symbol.DeclaredAccessibility.ToString().ToLowerInvariant(),
192197
Type = type,
193-
Kind = data.SymbolToKindCache.Get(typeSymbol)
198+
Kind = data.SymbolToKindCache.Get(typeSymbol),
199+
PersistableModelProxy = proxy is null ? null : TypeRef.FromINamedTypeSymbol(proxy, data.SymbolToKindCache)
194200
};
195201
})
196202
.Where(spec => spec is not null)
@@ -220,6 +226,19 @@ private void ReportDiagnosticAndEmitSource(
220226
/// </summary>
221227
internal Action<ModelReaderWriterContextGenerationSpec>? OnSourceEmitting { get; init; }
222228

229+
public static INamedTypeSymbol? GetProxyType(ITypeSymbol typeSymbol)
230+
{
231+
var persistableModelProxyAttribute = typeSymbol.GetAttributes()
232+
.FirstOrDefault(attr => attr.AttributeClass?.Name == "PersistableModelProxyAttribute");
233+
234+
if (persistableModelProxyAttribute == null || persistableModelProxyAttribute.ConstructorArguments.Length == 0)
235+
return null;
236+
237+
var proxyTypeArg = persistableModelProxyAttribute.ConstructorArguments[0];
238+
239+
return proxyTypeArg.Value as INamedTypeSymbol;
240+
}
241+
223242
private AttributeInfo GetAttributeInfo(AttributeSyntax? attribute, SemanticModel semanticModel)
224243
{
225244
{
@@ -448,7 +467,7 @@ private static bool IsModelReaderWriterContext(ClassDeclarationSyntax classDecla
448467
foreach (var baseItem in classDeclaration.BaseList.Types)
449468
{
450469
var baseTypeSymbol = semanticModel.GetSymbolInfo(baseItem.Type).Symbol as INamedTypeSymbol;
451-
if (baseTypeSymbol is null)
470+
if (baseTypeSymbol is null || baseTypeSymbol.TypeKind != TypeKind.Interface)
452471
{
453472
continue;
454473
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.ClientModel.Primitives;
5+
using System.ClientModel.Tests.Client.ModelReaderWriterTests.Models;
6+
using System.Collections.Generic;
7+
8+
namespace System.ClientModel.Tests.ModelReaderWriterTests.Models.BaseModels
9+
{
10+
public partial class ListTests
11+
{
12+
#nullable disable
13+
public class LocalContext : ModelReaderWriterContext
14+
{
15+
private static readonly Lazy<TestClientModelReaderWriterContext> s_libraryContext = new(() => new());
16+
private List_BaseModel_Builder _list_BaseModel_Builder;
17+
18+
protected override bool TryGetTypeBuilderCore(Type type, out ModelReaderWriterTypeBuilder builder)
19+
{
20+
builder = type switch
21+
{
22+
Type t when t == typeof(List<BaseModel>) => _list_BaseModel_Builder ??= new(),
23+
_ => GetFromDependencies(type)
24+
};
25+
return builder is not null;
26+
}
27+
28+
private ModelReaderWriterTypeBuilder GetFromDependencies(Type type)
29+
{
30+
if (s_libraryContext.Value.TryGetTypeBuilder(type, out ModelReaderWriterTypeBuilder builder))
31+
return builder;
32+
return null;
33+
}
34+
35+
private class List_BaseModel_Builder : ModelReaderWriterTypeBuilder
36+
{
37+
protected override Type BuilderType => typeof(List<BaseModel>);
38+
39+
protected override Type ItemType => typeof(BaseModel);
40+
41+
protected override object CreateInstance() => new List<BaseModel>();
42+
43+
protected override void AddItem(object collection, object item)
44+
=> ((List<BaseModel>)collection).Add((BaseModel)item);
45+
}
46+
}
47+
#nullable enable
48+
}
49+
}

sdk/core/System.ClientModel/tests/ModelReaderWriterTests/Models/BaseModels/ListTests.cs

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,23 @@
22
// Licensed under the MIT License.
33

44
using System.ClientModel.Primitives;
5+
#if SOURCE_GENERATOR
6+
using System.ClientModel.SourceGeneration.Tests;
7+
#else
58
using System.ClientModel.Tests.Client.ModelReaderWriterTests.Models;
9+
#endif
610
using System.Collections.Generic;
711
using NUnit.Framework;
812

913
namespace System.ClientModel.Tests.ModelReaderWriterTests.Models.BaseModels
1014
{
11-
public class ListTests : MrwCollectionTests<List<BaseModel>, BaseModel>
15+
public partial class ListTests : MrwCollectionTests<List<BaseModel>, BaseModel>
1216
{
17+
#if SOURCE_GENERATOR
18+
protected override ModelReaderWriterContext Context => BasicContext.Default;
19+
#else
1320
protected override ModelReaderWriterContext Context => new LocalContext();
21+
#endif
1422

1523
protected override string CollectionTypeName => "List<BaseModel>";
1624

@@ -35,42 +43,5 @@ protected override void CompareModels(BaseModel model, BaseModel model2, string
3543
ModelInstances.CompareModelZ(model, model2, format);
3644
}
3745
}
38-
39-
#nullable disable
40-
public class LocalContext : ModelReaderWriterContext
41-
{
42-
private static readonly Lazy<TestClientModelReaderWriterContext> s_libraryContext = new(() => new());
43-
private List_BaseModel_Builder _list_BaseModel_Builder;
44-
45-
protected override bool TryGetTypeBuilderCore(Type type, out ModelReaderWriterTypeBuilder builder)
46-
{
47-
builder = type switch
48-
{
49-
Type t when t == typeof(List<BaseModel>) => _list_BaseModel_Builder ??= new(),
50-
_ => GetFromDependencies(type)
51-
};
52-
return builder is not null;
53-
}
54-
55-
private ModelReaderWriterTypeBuilder GetFromDependencies(Type type)
56-
{
57-
if (s_libraryContext.Value.TryGetTypeBuilder(type, out ModelReaderWriterTypeBuilder builder))
58-
return builder;
59-
return null;
60-
}
61-
62-
private class List_BaseModel_Builder : ModelReaderWriterTypeBuilder
63-
{
64-
protected override Type BuilderType => typeof(List<BaseModel>);
65-
66-
protected override Type ItemType => typeof(BaseModel);
67-
68-
protected override object CreateInstance() => new List<BaseModel>();
69-
70-
protected override void AddItem(object collection, object item)
71-
=> ((List<BaseModel>)collection).Add((BaseModel)item);
72-
}
73-
}
74-
#nullable enable
7546
}
7647
}

sdk/core/System.ClientModel/tests/ModelReaderWriterTests/Models/BaseModels/ModelInstances.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
// Licensed under the MIT License.
33

44
using System.ClientModel.Primitives;
5+
#if SOURCE_GENERATOR
6+
using System.ClientModel.SourceGeneration.Tests;
7+
#else
58
using System.ClientModel.Tests.Client.ModelReaderWriterTests.Models;
9+
#endif
610
using System.Collections.Generic;
711
using System.Reflection;
812
using NUnit.Framework;
@@ -70,6 +74,8 @@ internal static void CompareModelZ(BaseModel expected, BaseModel actual, string
7074
var expectedRawData = GetRawData(expected);
7175
var actualRawData = GetRawData(actual);
7276

77+
Assert.AreEqual("UnknownBaseModel", actual.GetType().Name);
78+
7379
Assert.AreEqual(expected.Name!, actual.Name!);
7480
Assert.AreEqual(expected.Kind!, actual.Kind!);
7581
if (format == "J")

sdk/core/System.ClientModel/tests/client/ClientShared/OptionalProperty.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public static IList<T> ToList<T>(OptionalProperty<IList<T>> optional)
9999
}
100100
}
101101

102+
#if !SOURCE_GENERATOR
102103
public readonly struct OptionalProperty<T>
103104
{
104105
public OptionalProperty(T? value) : this()
@@ -113,3 +114,4 @@ public OptionalProperty(T? value) : this()
113114
public static implicit operator OptionalProperty<T>(T? value) => new OptionalProperty<T>(value);
114115
public static implicit operator T?(OptionalProperty<T> optional) => optional.Value;
115116
}
117+
#endif

sdk/core/System.ClientModel/tests/client/ModelReaderWriter/Models/DiscriminatorSet/BaseModel.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
using System.Collections.Generic;
77
using System.Text.Json;
88

9+
#if SOURCE_GENERATOR
10+
namespace System.ClientModel.SourceGeneration.Tests
11+
#else
912
namespace System.ClientModel.Tests.Client.ModelReaderWriterTests.Models
13+
#endif
1014
{
1115
[PersistableModelProxy(typeof(UnknownBaseModel))]
1216
public abstract class BaseModel : IJsonModel<BaseModel>

sdk/core/System.ClientModel/tests/client/ModelReaderWriter/Models/DiscriminatorSet/ModelX.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
using System.Linq;
88
using System.Text.Json;
99

10+
#if SOURCE_GENERATOR
11+
namespace System.ClientModel.SourceGeneration.Tests
12+
#else
1013
namespace System.ClientModel.Tests.Client.ModelReaderWriterTests.Models
14+
#endif
1115
{
1216
public class ModelX : BaseModel, IJsonModel<ModelX>
1317
{

sdk/core/System.ClientModel/tests/client/ModelReaderWriter/Models/DiscriminatorSet/ModelY.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
using System.Collections.Generic;
77
using System.Text.Json;
88

9+
#if SOURCE_GENERATOR
10+
namespace System.ClientModel.SourceGeneration.Tests
11+
#else
912
namespace System.ClientModel.Tests.Client.ModelReaderWriterTests.Models
13+
#endif
1014
{
1115
public class ModelY : BaseModel, IJsonModel<ModelY>
1216
{

0 commit comments

Comments
 (0)