-
Notifications
You must be signed in to change notification settings - Fork 318
Hierarchy building #8999
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
base: main
Are you sure you want to change the base?
Hierarchy building #8999
Conversation
|
No changes needing a change description found. |
...p/generator/Microsoft.TypeSpec.Generator/test/Providers/ModelProviders/ModelProviderTests.cs
Show resolved
Hide resolved
...ges/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs
Outdated
Show resolved
Hide resolved
...ges/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs
Show resolved
Hide resolved
| || (p.Property.IsDiscriminator && !overriddenProperties.Contains(p.Property) && (!isPrimaryConstructor || includeDiscriminatorParameter)) | ||
| || (!p.Property.IsDiscriminator && !overriddenProperties.Contains(p.Property)))); | ||
|
|
||
| if (includeDiscriminatorParameter && _inputModel.DiscriminatorProperty != null) |
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.
I think the filtering that we need to adjust happens here - https://github.com/microsoft/typespec/blob/main/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs#L586-L594. That filtering is designed for only one layer of inheritance for a single discriminator. Now that we support N layers for a single discriminator, we need to adjust the condition. This will allow us to not have special handling for creating the discriminator param, and the name/description will come directly from the property.
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.
Oh, so do you mean that rather than creating the discriminator parameter, I simply remove the if (isDirectBase) from GetAllBasePropertiesForConstructorInitialization this way I dont have to create the discriminator and do not need to create includeDiscriminatorParameter flag in BuildConstructorParameters?
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.
I think we still need some logic to do what the isDirectBase is currently doing. The purpose of that was so that we don't add base properties when there are nested discriminators from an ancestor further than the direct base. So I think you are right we can remove the isDirectBase check but we will need to add a new check that the discriminator property from the base model matches the current model's discriminator property.
...ges/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs
Outdated
Show resolved
Hide resolved
...ges/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs
Outdated
Show resolved
Hide resolved
...ges/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ModelProvider.cs
Outdated
Show resolved
Hide resolved
| public class ModelProvider : TypeProvider | ||
| { | ||
| private const string AdditionalBinaryDataPropsFieldDescription = "Keeps track of any properties unknown to the library."; | ||
| private const string DiscriminatorParameterName = "discriminatorValue"; |
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.
nit: I think we don't need these anymore
| /// This is needed when the model shares the same discriminator property name as its base model | ||
| /// AND has derived models, indicating it's an intermediate type in a discriminated union hierarchy. | ||
| /// </summary> | ||
| private bool ShouldHaveDualConstructorPattern() |
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.
Can we compute this and store in a field called _isMultiLevelDiscriminator?
| if (isDirectBase) | ||
| // Only include discriminator properties from the direct base that match the current model's discriminator property name. | ||
| // This handles N layers of inheritance while ensuring we don't include multiple discriminator parameters | ||
| if (isDirectBase && _inputModel.DiscriminatorProperty != null && |
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.
I think this should be if (isDirectBase || _isMultiLevelDiscriminator)
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.
Actually we probably need to add a parameter in this method (and check that instead) since we only want to do this for one of the constructors for multilevel discriminator models. Something like:
if (isDirectBase || includeHierarchyDiscriminator)| var constructors = new List<ConstructorProvider> { publicConstructor }; | ||
|
|
||
| // If this model needs dual constructor pattern, add the private protected constructor | ||
| if (ShouldHaveDualConstructorPattern()) |
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.
if it is a multiLevelDiscriminator I think we can just add the additional constructor and let the other constructor creation happen as is
|
Looks like the CI is failing |
This pull request introduces a new dual constructor pattern for intermediate models in discriminated union hierarchies, ensuring correct instantiation and inheritance when models share discriminator property names with their base models. It adds logic to detect when this pattern is needed, generates the appropriate constructors, and updates constructor initialization to support multi-layer discriminator scenarios. Several new tests are included to validate these changes.
Constructor Pattern Enhancements
ConstructorTypeenum to define different constructor generation strategies, supporting public, private protected, and internal constructors for various use cases.ModelProviderto detect when a model should use the dual constructor pattern (i.e., when it shares a discriminator property name with its base and has derived models).Constructor Initialization Logic
Testing Multi-Layer Discriminator Hierarchies
Minor Cleanup
discriminatedKindargument in a test setup for clarity.Addresses: Azure/azure-sdk-for-net#51958