Skip to content

Commit 34004ef

Browse files
committed
Skip external models from mocking
1 parent fe4d1e1 commit 34004ef

3 files changed

Lines changed: 34 additions & 0 deletions

File tree

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,16 @@ private static IReadOnlyList<ValueExpression> GetCtorArgs(
488488

489489
private static ModelProvider? GetModelToInstantiateForFactoryMethod(ModelProvider modelProvider)
490490
{
491+
// Externally-linked models are reused from another shipped package (e.g. the OpenAI .NET
492+
// SDK), so this library does not own or emit their constructors. Their real constructor
493+
// surface (accessibility and parameter set) is unknown here; emitting a
494+
// `new ExternalType(...)` mocking factory produces calls that may be inaccessible
495+
// (protected/internal) or have a non-matching arity. Skip factory generation for them.
496+
if (modelProvider.IsExternal)
497+
{
498+
return null;
499+
}
500+
491501
var fullConstructor = modelProvider.FullConstructor;
492502
if (modelProvider.DeclarationModifiers.HasFlag(TypeSignatureModifiers.Internal)
493503
|| fullConstructor.Signature.Parameters.Any(p => !p.Type.IsPublic && !IsEnumDiscriminator(p)))

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ public ModelProvider(InputModelType inputModel) : base(inputModel)
7777

7878
public bool IsUnknownDiscriminatorModel => _inputModel.IsUnknownDiscriminatorModel;
7979

80+
// Whether this model is reused from another shipped package (linked via an `external` block)
81+
// rather than emitted by this library. Such a type's constructor surface is owned elsewhere.
82+
internal bool IsExternal => _inputModel.External is not null;
83+
8084
public string? DiscriminatorValue => _inputModel.DiscriminatorValue;
8185

8286
private ValueExpression? _discriminatorValueExpression;

packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelFactories/ModelFactoryProviderTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@ public void SkipInternalModels()
3232
Assert.AreEqual(ModelList.Length - ModelList.Where(m => m.Access == "internal").Count(), modelFactory.Methods.Count);
3333
}
3434

35+
[Test]
36+
public void SkipExternalModels()
37+
{
38+
var external = new InputExternalTypeMetadata("OpenAI.Responses.ResponseTool", "OpenAI", "2.11.0");
39+
var externalModel = InputFactory.Model("ExternalTool", external: external);
40+
var localModel = InputFactory.Model("LocalThing");
41+
var instance = MockHelpers.LoadMockGenerator(
42+
inputNamespaceName: "Sample.Namespace",
43+
inputModelTypes: [externalModel, localModel]).Object;
44+
45+
var modelFactory = instance.OutputLibrary.ModelFactory.Value;
46+
47+
Assert.IsNull(
48+
modelFactory.Methods.FirstOrDefault(m => m.Signature.Name == "ExternalTool"),
49+
"Externally-linked models must not get a model factory method.");
50+
Assert.IsNotNull(
51+
modelFactory.Methods.FirstOrDefault(m => m.Signature.Name == "LocalThing"),
52+
"Local models must still get a model factory method.");
53+
}
54+
3555
[Test]
3656
public void ListParamShape()
3757
{

0 commit comments

Comments
 (0)