-
Notifications
You must be signed in to change notification settings - Fork 258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Skip empty clients #5652
Skip empty clients #5652
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -98,8 +98,33 @@ private ExtensibleEnumSerializationProvider[] CreateExtensibleEnumSerializations | |
} | ||
} | ||
|
||
ClientCache[inputClient] = client; | ||
return client; | ||
var result = client is not null && IsValidClient(inputClient, client) ? client : null; | ||
ClientCache[inputClient] = result; | ||
return result; | ||
} | ||
|
||
private bool IsValidClient(InputClient inputClient, ClientProvider client) | ||
{ | ||
// client is not valid if it has no operations, sub-client methods, or custom code methods | ||
if (inputClient.Operations.Count > 0) | ||
{ | ||
return true; | ||
} | ||
|
||
foreach (var subclient in client.SubClients) | ||
{ | ||
if (subclient.Methods.Count > 0) | ||
{ | ||
return true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to also check to see if the subclients have custom code defined. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added the check of custom code but only check methods of custom code for now. |
||
} | ||
} | ||
|
||
if (client.CustomCodeView?.Methods.Count > 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checking for the Methods isn't enough because the custom code may be using Properties, Fields, or even just doing something in the constructor. We should simply check whether there is custom code or not, and not worry about the individual members. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, it seems like custom code has a different criteria that if there is any custom code exists we should not skip the client? |
||
{ | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
protected virtual ClientProvider? CreateClientCore(InputClient inputClient) => new ClientProvider(inputClient); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,9 +26,13 @@ public class ClientProviderTests | |
private const string KeyAuthCategory = "WithKeyAuth"; | ||
private const string OAuth2Category = "WithOAuth2"; | ||
private const string TestClientName = "TestClient"; | ||
private static readonly InputClient _animalClient = new("animal", "", "AnimalClient description", [], [], TestClientName); | ||
private static readonly InputClient _dogClient = new("dog", "", "DogClient description", [], [], _animalClient.Name); | ||
private static readonly InputClient _huskyClient = new("husky", "", "HuskyClient description", [], [], _dogClient.Name); | ||
private static readonly InputOperation _inputOperation = InputFactory.Operation("HelloAgain", parameters: | ||
[ | ||
InputFactory.Parameter("p1", InputFactory.Array(InputPrimitiveType.String)) | ||
]); | ||
private static readonly InputClient _animalClient = new("animal", "", "AnimalClient description", [_inputOperation], [], TestClientName); | ||
private static readonly InputClient _dogClient = new("dog", "", "DogClient description", [_inputOperation], [], _animalClient.Name); | ||
private static readonly InputClient _huskyClient = new("husky", "", "HuskyClient description", [_inputOperation], [], _dogClient.Name); | ||
private static readonly InputModelType _spreadModel = InputFactory.Model( | ||
"spreadModel", | ||
usage: InputModelTypeUsage.Spread, | ||
|
@@ -63,6 +67,54 @@ public void SetUp() | |
clientPipelineApi: TestClientPipelineApi.Instance); | ||
} | ||
|
||
[Test] | ||
public void TestEmptyClient() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need a test that validates the behavior when custom code is added for the client and for a sub client. See https://github.com/microsoft/typespec/blob/main/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/ClientProviders/ClientProviderCustomizationTests.cs for examples of custom code tests. Probably the custom code tests should go in that file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added tests, but only for custom code with methods for now |
||
{ | ||
var client = InputFactory.Client(TestClientName); | ||
var plugin = MockHelpers.LoadMockPlugin(clients: () => [client]); | ||
|
||
var clientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is ClientProvider && t.Name == TestClientName); | ||
var restClientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is RestClientProvider && t.Name == TestClientName); | ||
Assert.IsNull(clientProvider); | ||
Assert.IsNull(restClientProvider); | ||
} | ||
|
||
[Test] | ||
public void TestNonEmptySubClient() | ||
{ | ||
var inputOperation = InputFactory.Operation("HelloAgain", parameters: | ||
[ | ||
InputFactory.Parameter("p1", InputFactory.Array(InputPrimitiveType.String)) | ||
]); | ||
var client = InputFactory.Client(TestClientName); | ||
var subClient = InputFactory.Client($"Sub{TestClientName}", [inputOperation], [], client.Name); | ||
var plugin = MockHelpers.LoadMockPlugin(clients: () => [client, subClient]); | ||
|
||
var subClientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is ClientProvider && t.Name == subClient.Name); | ||
Assert.IsNotNull(subClientProvider); | ||
|
||
var clientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is ClientProvider && t.Name == TestClientName); | ||
Assert.IsNotNull(clientProvider); | ||
} | ||
|
||
[Test] | ||
public void TestEmptySubClient() | ||
{ | ||
var client = InputFactory.Client(TestClientName); | ||
var subClient = InputFactory.Client($"Sub{TestClientName}", [], [], client.Name); | ||
var plugin = MockHelpers.LoadMockPlugin(clients: () => [client, subClient]); | ||
|
||
var subClientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is ClientProvider && t.Name == subClient.Name); | ||
var subRestClientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is RestClientProvider && t.Name == subClient.Name); | ||
Assert.IsNull(subClientProvider); | ||
Assert.IsNull(subRestClientProvider); | ||
|
||
var clientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is ClientProvider && t.Name == TestClientName); | ||
var restClientProvider = plugin.Object.OutputLibrary.TypeProviders.SingleOrDefault(t => t is RestClientProvider && t.Name == TestClientName); | ||
Assert.IsNull(clientProvider); | ||
Assert.IsNull(restClientProvider); | ||
} | ||
|
||
[Test] | ||
public void TestBuildProperties() | ||
{ | ||
|
@@ -736,7 +788,7 @@ public void TestApiVersionPathParameterOfClient(InputClient inputClient) | |
public void ClientProviderIsAddedToLibrary() | ||
{ | ||
var plugin = MockHelpers.LoadMockPlugin( | ||
clients: () => [new InputClient("test", "test", "test", [], [], null)]); | ||
clients: () => [new InputClient("test", "test", "test", [_inputOperation], [], null)]); | ||
|
||
Assert.AreEqual(1, plugin.Object.OutputLibrary.TypeProviders.OfType<ClientProvider>().Count()); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking for the Methods for the subclient isn't enough - we either need to check for the operations on the input client or the methods on the client and its REST client. I think adding an internal property like
HasOperations
orHasMethods
to ClientProvider should be added to encapsulate this logic.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial thought is that, we should have the same criteria for client, sub-client and custom code, which is any of them should have some methods.
For clientProvider, if there is no methods which means there is no operation or helper methods. Given RestClientProvider only contains methods of CreateRequestMethod, we should not need to check RestClientProvider.
Same thing for subClient, which is also a clientProvider.
For custom code, I don't understand why user would like to have a custom property or field to hold the empty client.
Do you have a use case for this?