Skip to content

Commit 7d0a7d4

Browse files
authored
Fully qualify context file (Azure#49352)
* fully qualify context file * pr fb and added typeref cache
1 parent ecf6604 commit 7d0a7d4

15 files changed

+191
-259
lines changed

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

Lines changed: 3 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,33 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
using System.Collections.Generic;
5-
using Microsoft.CodeAnalysis;
6-
74
namespace System.ClientModel.SourceGeneration;
85

96
internal sealed class TypeRef : IEquatable<TypeRef>
107
{
11-
public TypeRef(string name, string nameSpace, string assembly, TypeRef? itemType = default, int arrayRank = 0, string? alias = null)
8+
public TypeRef(string name, string nameSpace, string assembly, string fullyQualifiedName, TypeRef? itemType = default, int arrayRank = 0)
129
{
1310
Name = name;
1411
Namespace = nameSpace;
1512
ItemType = itemType;
1613
Assembly = assembly;
1714
ArrayRank = arrayRank;
18-
Alias = alias;
15+
FullyQualifiedName = fullyQualifiedName;
1916
}
2017

2118
public string Name { get; }
2219
public string Namespace { get; }
2320
public TypeRef? ItemType { get; }
2421
public string Assembly { get; }
2522
public int ArrayRank { get; }
26-
public string? Alias { get; }
23+
public string FullyQualifiedName { get; }
2724

2825
private string? _typeCaseName;
2926
public string TypeCaseName => _typeCaseName ??= Name.ToIdentifier(false);
3027

3128
private string? _camelCaseName;
3229
public string CamelCaseName => _camelCaseName ??= TypeCaseName.ToCamelCase();
3330

34-
private string? _typeCaseAlias;
35-
public string? TypeCaseAlias => _typeCaseAlias ??= Alias?.ToIdentifier(false);
36-
37-
private string? _camelCaseAlias;
38-
public string? CamelCaseAlias => _camelCaseAlias ??= TypeCaseAlias?.ToCamelCase();
39-
40-
internal static TypeRef FromTypeSymbol(ITypeSymbol symbol, TypeSymbolKindCache symbolToKindCache, Dictionary<ITypeSymbol, string> dupes)
41-
{
42-
dupes.TryGetValue(symbol, out string alias);
43-
if (symbol is INamedTypeSymbol namedTypeSymbol)
44-
{
45-
var name = symbol.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat);
46-
var itemSymbol = namedTypeSymbol.GetItemSymbol(symbolToKindCache);
47-
TypeRef? itemTypeRef = null;
48-
if (itemSymbol is not null)
49-
{
50-
itemTypeRef = FromTypeSymbol(itemSymbol, symbolToKindCache, dupes);
51-
if (itemTypeRef.Alias is not null)
52-
{
53-
alias = name.Replace(itemSymbol.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat), itemTypeRef.Alias);
54-
}
55-
}
56-
57-
return new TypeRef(
58-
symbol.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat),
59-
symbol.ContainingNamespace.ToDisplayString(),
60-
symbol.ContainingAssembly.ToDisplayString(),
61-
itemSymbol is null ? null : FromTypeSymbol(itemSymbol, symbolToKindCache, dupes),
62-
alias: alias);
63-
}
64-
else if (symbol is IArrayTypeSymbol arrayTypeSymbol)
65-
{
66-
var name = arrayTypeSymbol.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat).RemoveAsterisks();
67-
var elementType = FromTypeSymbol(arrayTypeSymbol.ElementType, symbolToKindCache, dupes);
68-
if (elementType.Alias is not null)
69-
{
70-
alias = name.Replace(arrayTypeSymbol.ElementType.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat), elementType.Alias);
71-
}
72-
73-
return new TypeRef(
74-
arrayTypeSymbol.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat).RemoveAsterisks(),
75-
elementType.Namespace,
76-
elementType.Assembly,
77-
elementType,
78-
arrayTypeSymbol.Rank,
79-
alias: alias);
80-
}
81-
else
82-
{
83-
throw new NotSupportedException($"Unexpected type {symbol.GetType()}");
84-
}
85-
}
86-
8731
internal bool IsSameAssembly(TypeRef other) => Assembly.Equals(other.Assembly, StringComparison.Ordinal);
8832

8933
public bool Equals(TypeRef? other)

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

Lines changed: 67 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ internal sealed partial class ModelReaderWriterContextGenerator
1111
{
1212
private sealed partial class Emitter
1313
{
14+
private const string s_modelReaderWriterContext = "global::System.ClientModel.Primitives.ModelReaderWriterContext";
15+
private const string s_modelReaderWriterTypeBuilder = "global::System.ClientModel.Primitives.ModelReaderWriterTypeBuilder";
16+
1417
internal void Emit(ModelReaderWriterContextGenerationSpec contextGenerationSpec)
1518
{
1619
EmitContextClass(contextGenerationSpec);
@@ -34,70 +37,54 @@ private void EmitContextClass(ModelReaderWriterContextGenerationSpec contextGene
3437
{
3538
builder.AppendLine(indent, $"using {nameSpace};");
3639
}
37-
foreach (var typeRef in contextGenerationSpec.GetAllTypeRefs())
38-
{
39-
if (typeRef.Alias is null || typeRef.ItemType is not null)
40-
continue;
41-
42-
builder.AppendLine(indent, $"using {typeRef.Alias} = {typeRef.Namespace}.{typeRef.TypeCaseName.Remove(typeRef.TypeCaseName.Length - 1)};");
43-
if (contextGenerationSpec.Type.IsSameAssembly(typeRef))
44-
{
45-
builder.AppendLine(indent, $"using {typeRef.Alias}_Builder = {typeRef.Namespace}.{typeRef.TypeCaseName}Builder;");
46-
}
47-
}
4840
builder.AppendLine();
4941

5042
builder.AppendLine(indent, $"namespace {contextGenerationSpec.Type.Namespace};");
5143
builder.AppendLine();
5244

53-
builder.AppendLine(indent, $"{contextGenerationSpec.Modifier} partial class {contextName} : ModelReaderWriterContext");
45+
builder.AppendLine(indent, $"{contextGenerationSpec.Modifier} partial class {contextName} : {s_modelReaderWriterContext}");
5446
builder.AppendLine(indent, "{");
5547
indent++;
5648

57-
builder.AppendLine(indent, "private readonly Dictionary<Type, Func<ModelReaderWriterTypeBuilder>> _typeBuilderFactories = [];");
49+
builder.Append(indent, "private readonly ");
50+
builder.AppendType(typeof(Dictionary<,>));
51+
builder.Append("<");
52+
builder.AppendType(typeof(Type));
53+
builder.Append(", ");
54+
builder.AppendType(typeof(Func<>));
55+
builder.Append("<");
56+
builder.AppendLine($"{s_modelReaderWriterTypeBuilder}>> _typeBuilderFactories = new();");
57+
58+
builder.Append(indent, "private readonly ");
59+
builder.AppendType(typeof(Dictionary<,>));
60+
builder.Append("<");
61+
builder.AppendType(typeof(Type));
62+
builder.Append(", ");
63+
builder.AppendLine($"{s_modelReaderWriterTypeBuilder}> _typeBuilders = new();");
5864
builder.AppendLine();
5965

6066
if (contextGenerationSpec.ReferencedContexts.Count > 0)
6167
{
68+
builder.Append(indent, "private static readonly ");
69+
builder.AppendType(typeof(Dictionary<,>));
70+
builder.Append("<");
71+
builder.AppendType(typeof(Type));
72+
builder.Append(", ");
73+
builder.Append(s_modelReaderWriterContext);
74+
builder.AppendLine("> s_referenceContexts = new()");
75+
builder.AppendLine(indent, "{");
76+
indent++;
6277
foreach (var referencedContext in contextGenerationSpec.ReferencedContexts)
6378
{
64-
builder.AppendLine(indent, $"private static readonly {referencedContext.Name} s_{referencedContext.CamelCaseName}Library = new();");
79+
builder.AppendLine(indent, $"{{ typeof({referencedContext.FullyQualifiedName}), new {referencedContext.FullyQualifiedName}() }},");
6580
}
81+
indent--;
82+
builder.AppendLine(indent, "};");
6683
builder.AppendLine();
6784
}
6885

6986
if (contextGenerationSpec.TypeBuilders.Count > 0)
7087
{
71-
foreach (var modelInfo in contextGenerationSpec.TypeBuilders)
72-
{
73-
builder.Append(indent, "private ");
74-
string typeCase;
75-
string camelCase;
76-
if (modelInfo.Type.Alias is not null)
77-
{
78-
typeCase = $"{modelInfo.Type.TypeCaseAlias}Builder";
79-
camelCase = $"_{modelInfo.Type.CamelCaseAlias}Builder";
80-
}
81-
else
82-
{
83-
typeCase = $"{modelInfo.Type.TypeCaseName}Builder";
84-
camelCase = $"_{modelInfo.Type.CamelCaseName}Builder";
85-
}
86-
87-
if (ShouldGenerateAsLocal(contextGenerationSpec, modelInfo))
88-
{
89-
builder.Append(typeCase);
90-
builder.Append(" ");
91-
}
92-
else
93-
{
94-
builder.Append("ModelReaderWriterTypeBuilder ");
95-
}
96-
builder.Append(camelCase);
97-
builder.AppendLine(";");
98-
}
99-
builder.AppendLine();
100-
10188
builder.AppendLine(indent, $"private static {contextName} _{contextName.ToCamelCase()};");
10289
builder.AppendLine(indent, "/// <summary> Gets the default instance </summary>");
10390
builder.AppendLine(indent, $"public static {contextName} Default => _{contextName.ToCamelCase()} ??= new();");
@@ -108,27 +95,14 @@ private void EmitContextClass(ModelReaderWriterContextGenerationSpec contextGene
10895
indent++;
10996
foreach (var modelInfo in contextGenerationSpec.TypeBuilders)
11097
{
111-
string typeofName;
112-
string camelCase;
113-
if (modelInfo.Type.Alias is not null)
114-
{
115-
typeofName = modelInfo.Type.Alias;
116-
camelCase = $"_{modelInfo.Type.CamelCaseAlias}Builder";
117-
}
118-
else
119-
{
120-
typeofName = modelInfo.Type.Name;
121-
camelCase = $"_{modelInfo.Type.CamelCaseName}Builder";
122-
}
123-
124-
builder.Append(indent, $"_typeBuilderFactories.Add(typeof({typeofName}), () => {camelCase} ??=");
98+
builder.Append(indent, $"_typeBuilderFactories.Add(typeof({modelInfo.Type.FullyQualifiedName}), () => ");
12599
if (ShouldGenerateAsLocal(contextGenerationSpec, modelInfo))
126100
{
127-
builder.AppendLine(" new());");
101+
builder.AppendLine($" new global::{modelInfo.Type.GetInnerItemType().Namespace}.{modelInfo.Type.TypeCaseName}Builder());");
128102
}
129103
else
130104
{
131-
builder.AppendLine($" s_{modelInfo.ContextType.CamelCaseName}Library.GetTypeBuilder(typeof({typeofName})));");
105+
builder.AppendLine($" s_referenceContexts[typeof({modelInfo.ContextType.FullyQualifiedName})].GetTypeBuilder(typeof({modelInfo.Type.FullyQualifiedName})));");
132106
}
133107
}
134108
builder.AppendLine();
@@ -141,29 +115,41 @@ private void EmitContextClass(ModelReaderWriterContextGenerationSpec contextGene
141115
}
142116

143117
builder.AppendLine(indent, "/// <inheritdoc/>");
144-
builder.AppendLine(indent, "protected override bool TryGetTypeBuilderCore(Type type, out ModelReaderWriterTypeBuilder builder)");
118+
builder.Append(indent, "protected override bool TryGetTypeBuilderCore(");
119+
builder.AppendType(typeof(Type));
120+
builder.AppendLine($" type, out {s_modelReaderWriterTypeBuilder} builder)");
121+
builder.AppendLine(indent, "{");
122+
indent++;
123+
builder.AppendLine(indent, "if (_typeBuilders.TryGetValue(type, out builder))");
145124
builder.AppendLine(indent, "{");
146125
indent++;
126+
builder.AppendLine(indent, "return true;");
127+
indent--;
128+
builder.AppendLine(indent, "}");
129+
builder.AppendLine();
147130
builder.AppendLine(indent, "if (_typeBuilderFactories.TryGetValue(type, out var factory))");
148131
builder.AppendLine(indent, "{");
149132
indent++;
150133
builder.AppendLine(indent, "builder = factory();");
134+
builder.AppendLine(indent, "_typeBuilders.Add(type, builder);");
151135
builder.AppendLine(indent, "return true;");
152136
indent--;
153137
builder.AppendLine(indent, "}");
154138
builder.AppendLine();
155139
if (contextGenerationSpec.ReferencedContexts.Count > 0)
156140
{
157-
for (int i = 0; i < contextGenerationSpec.ReferencedContexts.Count; i++)
158-
{
159-
var referencedContext = contextGenerationSpec.ReferencedContexts[i];
160-
builder.AppendLine(indent, $"if (s_{referencedContext.CamelCaseName}Library.TryGetTypeBuilder(type, out builder))");
161-
builder.AppendLine(indent, "{");
162-
indent++;
163-
builder.AppendLine(indent, "return true;");
164-
indent--;
165-
builder.AppendLine(indent, "}");
166-
}
141+
builder.AppendLine(indent, "foreach(var kvp in s_referenceContexts)");
142+
builder.AppendLine(indent, "{");
143+
indent++;
144+
builder.AppendLine(indent, $"if (kvp.Value.TryGetTypeBuilder(type, out builder))");
145+
builder.AppendLine(indent, "{");
146+
indent++;
147+
builder.AppendLine(indent, $"_typeBuilders.Add(type, builder);");
148+
builder.AppendLine(indent, "return true;");
149+
indent--;
150+
builder.AppendLine(indent, "}");
151+
indent--;
152+
builder.AppendLine(indent, "}");
167153
builder.AppendLine();
168154
}
169155
else
@@ -175,7 +161,15 @@ private void EmitContextClass(ModelReaderWriterContextGenerationSpec contextGene
175161
builder.AppendLine(indent, "}");
176162
builder.AppendLine();
177163

178-
builder.AppendLine(indent, $"partial void AddAdditionalFactories(Dictionary<Type, Func<ModelReaderWriterTypeBuilder>> factories);");
164+
builder.Append(indent, "partial void AddAdditionalFactories(");
165+
builder.AppendType(typeof(Dictionary<,>));
166+
builder.Append("<");
167+
builder.AppendType(typeof(Type));
168+
builder.Append(", ");
169+
builder.AppendType(typeof(Func<>));
170+
builder.Append("<");
171+
builder.Append(s_modelReaderWriterTypeBuilder);
172+
builder.AppendLine(">> factories);");
179173

180174
indent--;
181175
builder.AppendLine(indent, "}");
@@ -222,9 +216,7 @@ private void EmitTypeBuilder(TypeBuilderSpec modelInfo, TypeRef context)
222216
builder.AppendLine(indent, $"namespace {innerItemType.Namespace};");
223217
builder.AppendLine();
224218

225-
var className = modelInfo.Type.ItemType is null || modelInfo.Type.Alias is null ? modelInfo.Type.TypeCaseName : modelInfo.Type.TypeCaseAlias;
226-
227-
builder.AppendLine(indent, $"internal class {className}Builder : ModelReaderWriterTypeBuilder");
219+
builder.AppendLine(indent, $"internal class {modelInfo.Type.TypeCaseName}Builder : ModelReaderWriterTypeBuilder");
228220
builder.AppendLine(indent, "{");
229221
indent++;
230222

0 commit comments

Comments
 (0)