1+ using System ;
12using System . IO ;
23using GitVersion . Model . Configuration ;
4+ using YamlDotNet . Core ;
5+ using YamlDotNet . Core . Events ;
36using YamlDotNet . Serialization ;
47using YamlDotNet . Serialization . NamingConventions ;
58
@@ -11,6 +14,7 @@ public static Config Read(TextReader reader)
1114 {
1215 var deserializer = new DeserializerBuilder ( )
1316 . WithNamingConvention ( HyphenatedNamingConvention . Instance )
17+ . WithTypeConverter ( new YamlNullableEnumTypeConverter ( ) )
1418 . Build ( ) ;
1519 var deserialize = deserializer . Deserialize < Config > ( reader ) ;
1620 return deserialize ?? new Config ( ) ;
@@ -21,8 +25,70 @@ public static void Write(Config config, TextWriter writer)
2125 var serializer = new SerializerBuilder ( )
2226 . ConfigureDefaultValuesHandling ( DefaultValuesHandling . OmitDefaults )
2327 . WithNamingConvention ( HyphenatedNamingConvention . Instance )
28+ . WithTypeConverter ( new YamlNullableEnumTypeConverter ( ) )
2429 . Build ( ) ;
2530 serializer . Serialize ( writer , config ) ;
2631 }
2732 }
33+
34+ public class YamlNullableEnumTypeConverter : IYamlTypeConverter
35+ {
36+ public bool Accepts ( Type type )
37+ {
38+ return Nullable . GetUnderlyingType ( type ) ? . IsEnum ?? false ;
39+ }
40+
41+ public object ReadYaml ( IParser parser , Type type )
42+ {
43+ type = Nullable . GetUnderlyingType ( type ) ?? throw new ArgumentException ( "Expected nullable enum type for ReadYaml" ) ;
44+
45+ if ( parser . Accept < NodeEvent > ( out var @event ) )
46+ {
47+ if ( NodeIsNull ( @event ) )
48+ {
49+ parser . SkipThisAndNestedEvents ( ) ;
50+ return null ;
51+ }
52+ }
53+
54+ var scalar = parser . Consume < Scalar > ( ) ;
55+ try
56+ {
57+ return Enum . Parse ( type , scalar . Value , ignoreCase : true ) ;
58+ }
59+ catch ( Exception ex )
60+ {
61+ throw new Exception ( $ "Invalid value: \" { scalar . Value } \" for { type . Name } ", ex ) ;
62+ }
63+ }
64+
65+ public void WriteYaml ( IEmitter emitter , object value , Type type )
66+ {
67+ type = Nullable . GetUnderlyingType ( type ) ?? throw new ArgumentException ( "Expected nullable enum type for WriteYaml" ) ;
68+
69+ if ( value != null )
70+ {
71+ var toWrite = Enum . GetName ( type , value ) ?? throw new InvalidOperationException ( $ "Invalid value { value } for enum: { type } ") ;
72+ emitter . Emit ( new Scalar ( null , null , toWrite , ScalarStyle . Any , true , false ) ) ;
73+ }
74+ }
75+
76+ private static bool NodeIsNull ( NodeEvent nodeEvent )
77+ {
78+ // http://yaml.org/type/null.html
79+
80+ if ( nodeEvent . Tag == "tag:yaml.org,2002:null" )
81+ {
82+ return true ;
83+ }
84+
85+ if ( nodeEvent is Scalar scalar && scalar . Style == ScalarStyle . Plain )
86+ {
87+ var value = scalar . Value ;
88+ return value is "" or "~" or "null" or "Null" or "NULL" ;
89+ }
90+
91+ return false ;
92+ }
93+ }
2894}
0 commit comments