Azure / autorest.csharp

Extension for AutoRest (https://github.com/Azure/autorest) that generates C# code
MIT License
142 stars 165 forks source link

Emitter typespec-csharp crashed when operations under operation groups have same name. #4744

Open Han-msft opened 3 months ago

Han-msft commented 3 months ago

Describe the issue or request Spec: https://github.com/Azure/azure-rest-api-specs/blob/be45b922eca7b7753e74e2074127f395223fa13e/specification/ai/Face/client.tsp

@client({
  name: "FaceServiceClient",
  service: Face
})
namespace FaceServiceClient
{
  @operationGroup
  interface FaceList {
    create is FaceListOperations.createFaceList;
    delete is FaceListOperations.deleteFaceList;
    ...
  }

  @operationGroup
  interface LargeFaceList {
    create is FaceListOperations.createLargeFaceList;
    delete is FaceListOperations.deleteLargeFaceList;
   ...
  }
...
}

Exception: https://dev.azure.com/azure-sdk/internal/_build/results?buildId=3806374&view=logs&j=03afb3bb-7296-55ad-aa07-ceee610c73b2&t=0f320c29-1c90-5304-d2d3-c58a6bb76437&l=171

07:37:38.584 cmdout     [Invoke-GenerateAndBuildV2.ps1]   Unhandled exception. System.Text.Json.JsonException: Failed to add reference ID 'CreateRequest.DerivedModels' with value type 'System.Collections.Generic.List`1[AutoRest.CSharp.Common.Input.InputModelType]'
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecReferenceHandler.TypeSpecReferenceResolver.AddReference(String referenceId, Object value) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecReferenceHandler.cs:line 29
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputModelTypeConverter.CreateInputModelTypeInstance(String id, String name, String ns, String accessibility, String deprecated, String description, String usageString, String discriminatorValue, String discriminatorPropertyValue, InputModelType baseModel, IReadOnlyList`1 properties, InputDictionaryType inheritedDictionaryType, Boolean isNullable, ReferenceResolver resolver) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputModelTypeConverter.cs:line 112
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputModelTypeConverter.CreateModelType(Utf8JsonReader& reader, String id, String name, JsonSerializerOptions options, ReferenceResolver resolver) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputModelTypeConverter.cs:line 80
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputTypeConverter.CreateDerivedType(Utf8JsonReader& reader, String id, String kind, String name, JsonSerializerOptions options) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputTypeConverter.cs:line 80
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputTypeConverter.CreateObject(Utf8JsonReader& reader, JsonSerializerOptions options) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputTypeConverter.cs:line 60
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputTypeConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputTypeConverter.cs:line 37
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.Utf8JsonReaderExtensions.ReadWithConverter[T](Utf8JsonReader& reader, JsonSerializerOptions options) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\Utf8JsonReaderExtensions.cs:line 181
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.Utf8JsonReaderExtensions.TryReadWithConverter[T](Utf8JsonReader& reader, String propertyName, JsonSerializerOptions options, T& value) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\Utf8JsonReaderExtensions.cs:line 145
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputParameterConverter.CreateInputParameter(Utf8JsonReader& reader, String id, String name, JsonSerializerOptions options, ReferenceResolver resolver) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputParameterConverter.cs:line 50
07:37:38.585 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputParameterConverter.ReadInputParameter(Utf8JsonReader& reader, JsonSerializerOptions options, ReferenceResolver resolver) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputParameterConverter.cs:line 26
07:37:38.586 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputParameterConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputParameterConverter.cs:line 20
07:37:38.586 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.Utf8JsonReaderExtensions.ReadWithConverter[T](Utf8JsonReader& reader, JsonSerializerOptions options) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\Utf8JsonReaderExtensions.cs:line 181
07:37:38.586 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.Utf8JsonReaderExtensions.TryReadWithConverter[T](Utf8JsonReader& reader, String propertyName, JsonSerializerOptions options, IReadOnlyList`1& value) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\Utf8JsonReaderExtensions.cs:line 171
07:37:38.586 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputOperationConverter.CreateOperation(Utf8JsonReader& reader, String id, String name, JsonSerializerOptions options, ReferenceResolver resolver) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputOperationConverter.cs:line 54
07:37:38.586 cmdout     [Invoke-GenerateAndBuildV2.ps1]      at AutoRest.CSharp.Common.Input.TypeSpecInputOperationConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options) in D:\a\_work\1\s\autorest.csharp\src\AutoRest.CSharp\Common\Input\InputTypes\Serialization\TypeSpecInputOperationConverter.cs:line 24
ArcturusZhang commented 3 months ago

Looks like this is caused when we made up a name, we did not check for duplication, and now it duplicates and causes issues https://github.com/Azure/autorest.csharp/blob/187e6f8d3c6634019bcf4ce3db887626a4efa489/src/TypeSpec.Extension/Emitter.Csharp/src/lib/operation.ts#L128

archerzz commented 3 months ago

This is because TCGC failed to give alias model a name. That alias model is used in a very complex way. See the bug I created on TCGC: https://github.com/Azure/typespec-azure/issues/918

After TCGC getAllModels adoption, at runtime our emitter should not go to the branch mentioned by dapeng above. You can look a few lines above, and you'll realize that we invoke loadBodyParameter() will invoke TCGC to get the type. Ideally the return type should have a name.

archerzz commented 3 months ago

@Han-msft I would suggest to not use alias models. Try to define a normal model. I changed alias CreateCollectionOptions to model CreateCollectionOptions, and at least the same error doesn't appear.

Han-msft commented 3 months ago

@archerzz is there any way to keep properties under CreateCollectionOptions to be spread as method input parameter? That's why we define it as alias.

archerzz commented 3 months ago

@archerzz is there any way to keep properties under CreateCollectionOptions to be spread as method input parameter? That's why we define it as alias.

@Han-msft There is discussion to unify the behavior of parameter spreading. In the future, named model is also spread as method input parameters: https://github.com/Azure/typespec-azure/issues/612

The only uncertainty is when we will implement the change.

archerzz commented 2 weeks ago

@Han-msft would you mind if you could try the latest generator again? The issue should have been resolved. Thanks.

Han-msft commented 2 weeks ago

@archerzz issue resolved after we switched to model for spread parameters.