Skip to content

Commit 8f3ed98

Browse files
authored
Add additional tests around dependency checking (Azure#49210)
* add additional tests around dependency checking * default public if you have builders * remove implicit context * add extra assert * add xml docs for public members
1 parent 625474b commit 8f3ed98

18 files changed

+556
-260
lines changed

eng/Packages.Data.props

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@
281281
<!-- Note: Upgrading the .NET SDK version needs to be synchronized with the autorest.csharp repository -->
282282
<PackageReference Update="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="All"/>
283283
<PackageReference Update="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.2" PrivateAssets="All" />
284-
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version ="4.12.0" PrivateAssets="All" />
284+
<!-- Note: 4.0.0 is required to keep our shipped source generators compatible with most project targets like netstandard2.0-->
285+
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version ="4.0.0" PrivateAssets="All" />
285286
<PackageReference Update="Microsoft.CodeAnalysis.NetAnalyzers" Version="9.0.0" PrivateAssets="All" />
286287
<PackageReference Update="Microsoft.DotNet.ApiCompat" Version="5.0.0-beta.20467.1" PrivateAssets="All" />
287288
<PackageReference Update="Microsoft.DotNet.GenAPI" Version="5.0.0-beta.19552.1" PrivateAssets="All" />
Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,47 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
using System.Collections.Generic;
5-
using System.Linq;
64
using Microsoft.CodeAnalysis;
75

86
namespace System.ClientModel.SourceGeneration;
97

108
internal sealed class TypeRef : IEquatable<TypeRef>
119
{
12-
public TypeRef(string name, string nameSpace, string assembly, IEnumerable<TypeRef>? genericArguments = default, int arrayRank = 0)
10+
public TypeRef(string name, string nameSpace, string assembly, TypeRef? itemType = default, int arrayRank = 0)
1311
{
1412
Name = name;
1513
Namespace = nameSpace;
16-
GenericArguments = genericArguments is null ? [] : genericArguments.ToList();
14+
ItemType = itemType;
1715
Assembly = assembly;
1816
ArrayRank = arrayRank;
1917
}
2018

2119
public string Name { get; }
2220
public string Namespace { get; }
23-
public IReadOnlyList<TypeRef> GenericArguments { get; }
21+
public TypeRef? ItemType { get; }
2422
public string Assembly { get; }
2523
public int ArrayRank { get; }
2624

27-
internal static TypeRef FromINamedTypeSymbol(ISymbol symbol)
25+
internal static TypeRef FromINamedTypeSymbol(ITypeSymbol symbol, TypeSymbolKindCache symbolToKindCache)
2826
{
2927
if (symbol is INamedTypeSymbol namedTypeSymbol)
3028
{
31-
var typeArguments = namedTypeSymbol.TypeArguments.OfType<INamedTypeSymbol>().Select(FromINamedTypeSymbol);
29+
var itemSymbol = namedTypeSymbol.GetItemSymbol(symbolToKindCache);
3230

3331
return new TypeRef(
3432
symbol.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat),
3533
symbol.ContainingNamespace.ToDisplayString(),
3634
symbol.ContainingAssembly.ToDisplayString(),
37-
typeArguments);
35+
itemSymbol is null ? null : FromINamedTypeSymbol(itemSymbol, symbolToKindCache));
3836
}
3937
else if (symbol is IArrayTypeSymbol arrayTypeSymbol)
4038
{
41-
var elementType = FromINamedTypeSymbol(arrayTypeSymbol.ElementType);
39+
var elementType = FromINamedTypeSymbol(arrayTypeSymbol.ElementType, symbolToKindCache);
4240
return new TypeRef(
4341
arrayTypeSymbol.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat).RemoveAsterisks(),
4442
elementType.Namespace,
4543
elementType.Assembly,
46-
[elementType],
44+
elementType,
4745
arrayTypeSymbol.Rank);
4846
}
4947
else
@@ -52,6 +50,8 @@ internal static TypeRef FromINamedTypeSymbol(ISymbol symbol)
5250
}
5351
}
5452

53+
internal bool IsSameAssembly(TypeRef other) => Assembly.Equals(other.Assembly, StringComparison.Ordinal);
54+
5555
public bool Equals(TypeRef? other)
5656
=> other != null && Name == other.Name && Namespace == other.Namespace;
5757

@@ -63,4 +63,9 @@ public override int GetHashCode()
6363

6464
public override string ToString()
6565
=> $"{Namespace}.{Name}";
66+
67+
internal TypeRef GetInnerItemType()
68+
{
69+
return ItemType is null ? this : ItemType.GetInnerItemType();
70+
}
6671
}

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

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ internal void Emit(ModelReaderWriterContextGenerationSpec contextGenerationSpec)
3333

3434
int indent = 0;
3535
StringBuilder builder = new();
36+
37+
builder.AppendLine("// <auto-generated/>");
38+
builder.AppendLine();
39+
3640
builder.AppendLine(indent, "#nullable disable");
3741
builder.AppendLine();
3842

@@ -79,6 +83,7 @@ internal void Emit(ModelReaderWriterContextGenerationSpec contextGenerationSpec)
7983
builder.AppendLine();
8084

8185
builder.AppendLine(indent, $"private static {contextName} _{contextName.ToCamelCase()};");
86+
builder.AppendLine(indent, "/// <summary> Gets the default instance </summary>");
8287
builder.AppendLine(indent, $"public static {contextName} Default => _{contextName.ToCamelCase()} ??= new();");
8388
builder.AppendLine();
8489

@@ -106,6 +111,7 @@ internal void Emit(ModelReaderWriterContextGenerationSpec contextGenerationSpec)
106111
builder.AppendLine();
107112
}
108113

114+
builder.AppendLine(indent, "/// <inheritdoc/>");
109115
builder.AppendLine(indent, "protected override bool TryGetTypeBuilderCore(Type type, out ModelReaderWriterTypeBuilder builder)");
110116
builder.AppendLine(indent, "{");
111117
indent++;
@@ -161,7 +167,7 @@ private static bool ShouldGenerateAsLocal(ModelReaderWriterContextGenerationSpec
161167
return modelInfo.Kind == TypeBuilderKind.Array ||
162168
modelInfo.Kind == TypeBuilderKind.MultiDimensionalArray ||
163169
!referenceContextLookup.ContainsKey(modelInfo.Type.Assembly) ||
164-
IsSameAssembly(contextGenerationSpec.Type, modelInfo.Type);
170+
contextGenerationSpec.Type.IsSameAssembly(modelInfo.Type);
165171
}
166172

167173
private static void EmitModelInfo(
@@ -193,7 +199,6 @@ private static void EmitModelInfo(
193199
EmitReadOnlyMemoryModelInfo(indent, builder, modelInfo, context, referenceContextLookup, identifierLookup);
194200
break;
195201
default:
196-
//give warning and skip
197202
break;
198203
}
199204
}
@@ -206,7 +211,7 @@ private static void EmitReadOnlyMemoryModelInfo(
206211
Dictionary<string, TypeRef> referenceContextLookup,
207212
Dictionary<TypeRef, (string TypeCase, string CamelCase)> identifierLookup)
208213
{
209-
var elementType = modelInfo.Type.GenericArguments[0];
214+
var elementType = modelInfo.Type.ItemType!;
210215
builder.AppendLine(indent, $"internal class {identifierLookup[modelInfo.Type].TypeCase}Builder : ModelReaderWriterTypeBuilder");
211216
builder.AppendLine(indent, "{");
212217
indent++;
@@ -262,7 +267,7 @@ private static void EmitMultiDimensionalArrayModelInfo(
262267
Dictionary<string, TypeRef> referenceContextLookup,
263268
Dictionary<TypeRef, (string TypeCase, string CamelCase)> identifierLookup)
264269
{
265-
var elementType = modelInfo.Type.GenericArguments[0];
270+
var elementType = modelInfo.Type.ItemType!;
266271
builder.AppendLine(indent, $"internal class {identifierLookup[modelInfo.Type].TypeCase}Builder : ModelReaderWriterTypeBuilder");
267272
builder.AppendLine(indent, "{");
268273
indent++;
@@ -329,7 +334,7 @@ private static void EmitArrayModelInfo(
329334
Dictionary<string, TypeRef> referenceContextLookup,
330335
Dictionary<TypeRef, (string TypeCase, string CamelCase)> identifierLookup)
331336
{
332-
var elementType = modelInfo.Type.GenericArguments[0];
337+
var elementType = modelInfo.Type.ItemType!;
333338
builder.AppendLine(indent, $"internal class {identifierLookup[modelInfo.Type].TypeCase}Builder : ModelReaderWriterTypeBuilder");
334339
builder.AppendLine(indent, "{");
335340
indent++;
@@ -366,7 +371,7 @@ private static void EmitDictionaryModelInfo(
366371
Dictionary<string, TypeRef> referenceContextLookup,
367372
Dictionary<TypeRef, (string TypeCase, string CamelCase)> identifierLookup)
368373
{
369-
var elementType = modelInfo.Type.GenericArguments[1];
374+
var elementType = modelInfo.Type.ItemType!;
370375
builder.AppendLine(indent, $"internal class {identifierLookup[modelInfo.Type].TypeCase}Builder : ModelReaderWriterTypeBuilder");
371376
builder.AppendLine(indent, "{");
372377
indent++;
@@ -389,21 +394,6 @@ private static void EmitDictionaryModelInfo(
389394
builder.AppendLine(indent, "}");
390395
}
391396

392-
private static bool IsSameAssembly(TypeRef context, TypeRef elementType)
393-
{
394-
if (context.Assembly.Equals(elementType.Assembly, StringComparison.Ordinal))
395-
return true;
396-
397-
//If we made the context implicitly its assembly will be a simple name
398-
//TestAssembly
399-
//vs
400-
//TestAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
401-
if (!context.Assembly.AsSpan().Contains(", Version".AsSpan(), StringComparison.Ordinal))
402-
return elementType.Assembly.StartsWith(context.Assembly, StringComparison.Ordinal);
403-
404-
return false;
405-
}
406-
407397
private static void EmitEnumerableModelInfo(
408398
int indent,
409399
StringBuilder builder,
@@ -412,7 +402,7 @@ private static void EmitEnumerableModelInfo(
412402
Dictionary<string, TypeRef> referenceContextLookup,
413403
Dictionary<TypeRef, (string TypeCase, string CamelCase)> identifierLookup)
414404
{
415-
var elementType = modelInfo.Type.GenericArguments[0];
405+
var elementType = modelInfo.Type.ItemType!;
416406
builder.AppendLine(indent, $"internal class {identifierLookup[modelInfo.Type].TypeCase}Builder : ModelReaderWriterTypeBuilder");
417407
builder.AppendLine(indent, "{");
418408
indent++;
@@ -442,7 +432,7 @@ private static void EmitPersistableModelInfo(
442432
TypeRef context,
443433
Dictionary<TypeRef, (string TypeCase, string CamelCase)> identifierLookup)
444434
{
445-
if (IsSameAssembly(context, modelInfo.Type))
435+
if (context.IsSameAssembly(modelInfo.Type))
446436
{
447437
builder.AppendLine(indent, $"internal class {identifierLookup[modelInfo.Type].TypeCase}Builder : ModelReaderWriterTypeBuilder");
448438
builder.AppendLine(indent, "{");
@@ -483,17 +473,17 @@ private HashSet<string> GetNameSpaces(ModelReaderWriterContextGenerationSpec con
483473
return namespaces;
484474
}
485475

486-
private void AddNamespaces(HashSet<string> namespaces, TypeRef referencedContext, HashSet<TypeRef> visited)
476+
private void AddNamespaces(HashSet<string> namespaces, TypeRef type, HashSet<TypeRef> visited)
487477
{
488-
if (!visited.Add(referencedContext))
478+
if (!visited.Add(type))
489479
{
490480
return;
491481
}
492482

493-
namespaces.Add(referencedContext.Namespace);
494-
foreach (var genericArgument in referencedContext.GenericArguments)
483+
namespaces.Add(type.Namespace);
484+
if (type.ItemType is not null)
495485
{
496-
AddNamespaces(namespaces, genericArgument, visited);
486+
AddNamespaces(namespaces, type.ItemType, visited);
497487
}
498488
}
499489

0 commit comments

Comments
 (0)