Suppress SHARPYAML002 when a converter handles the type#140
Merged
xoofx merged 1 commit intoMar 29, 2026
Merged
Conversation
The source generator SHARPYAML002 diagnostic now checks for converters before reporting unsupported member types. Previously, types like HttpMethod or IPEndPoint would trigger SHARPYAML002 even when a custom YamlConverter<T> was registered via [YamlSourceGenerationOptions] or [YamlConverter] attributes. The validation now skips the diagnostic when: - The member has a [YamlConverter(typeof(...))] attribute - The member type has a [YamlConverter(typeof(...))] attribute - A context-level YamlConverter<T> handles the member type This applies to direct member types, array/list element types, and dictionary value types. Nullable<T> value types are unwrapped before matching against converters. Added 9 tests covering all suppression paths and regression cases.
3ec240c to
46162a4
Compare
Contributor
Author
|
Thanks for the latest merges, @xoofx. I will rebase this one onto main and test a bit more before removing it from draft. |
Contributor
Author
|
Looking great now! @xoofx, whenever you get a chance… |
Contributor
Author
|
BTW: These should be the last changes… at least until my next brilliant idea strikes. 😄 And if it’s not asking too much… how about a teeny-tiny new release? Just a microscopic one? 😉 |
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
The SHARPYAML002 diagnostic fires for member types that are not registered via
[YamlSerializable]and are not built-in scalars. However, if a custom converter already handles the type, the diagnostic is a false positive — the generated POCO code path is never reached at runtime.This is a practical blocker for types like
HttpMethod,IPEndPoint, andIPAddress:HttpMethodvia[YamlSerializable(typeof(HttpMethod))]fails with CS0176 because the generator accesses static properties via an instance reference.IPEndPointtriggers a nested SHARPYAML002 forIPAddress, which in turn has its own members — creating an unsolvable cascade.Applications that provide custom
YamlConverter<HttpMethod>andYamlConverter<IPEndPoint>(registered via[YamlSourceGenerationOptions(Converters = [...])]) have no way to suppress the diagnostic today, forcing them to exclude affected types from the source-gen context entirely.In a real-world application (Deucalion — an ASP.NET Core + SignalR monitoring app), this excludes 6 out of 10 model types from source generation due to transitive dependencies on converter-handled types.
Solution
The SHARPYAML002 validation loop in
YamlSerializerContextGenerator.EmitContext()now checks for converters before reporting the diagnostic. A newIsTypeHandledByConverterhelper checks three conditions:[YamlConverter(typeof(...))]attribute — if the member itself declares a converter, skip the entire member.[YamlConverter(typeof(...))]attribute — if the member's type is decorated with[YamlConverter], skip the diagnostic.YamlConverter<T>registration — walks the base type chain of each converter in[YamlSourceGenerationOptions(Converters = [...])]to findYamlConverter<T>and matchesTagainst the member type.These checks apply to:
HttpMethod? Method)List<CustomType>)Dictionary<string, CustomType>)Nullable<T>value types are unwrapped before matching (aYamlConverter<MyStruct>suppresses SHARPYAML002 forMyStruct?members).Tests
Added 9 new diagnostic tests covering all suppression paths:
SHARPYAML002_IsSuppressed_WhenContextLevelConverterHandlesMemberTypeYamlConverter<T>suppresses for direct memberSHARPYAML002_IsSuppressed_WhenMemberHasYamlConverterAttribute[YamlConverter]on member suppressesSHARPYAML002_IsSuppressed_WhenTypeHasYamlConverterAttribute[YamlConverter]on type suppressesSHARPYAML002_IsSuppressed_WhenContextConverterHandlesArrayElementTypeList<T>elementsSHARPYAML002_IsSuppressed_WhenContextConverterHandlesDictionaryValueTypeDictionary<K,V>valuesSHARPYAML002_IsSuppressed_WhenConverterInheritsFromAnotherConverterYamlConverter<T>) suppressesSHARPYAML002_IsSuppressed_WhenContextConverterHandlesNullableValueTypeYamlConverter<T>suppresses forT?membersSHARPYAML002_StillFires_WhenNoConverterHandlesTypeSHARPYAML002_StillFires_WhenConverterHandlesDifferentTypeAll 628 existing tests continue to pass.