@@ -16,6 +16,8 @@ namespace Microsoft.TypeSpec.Generator.ClientModel.Providers
1616{
1717 public class ModelReaderWriterContextDefinition : TypeProvider
1818 {
19+ private const string DefaultObsoleteDiagnosticId = "CS0618" ;
20+
1921 internal static readonly string s_name = $ "{ RemovePeriods ( ScmCodeModelGenerator . Instance . TypeFactory . PrimaryNamespace ) } Context";
2022
2123 protected override string BuildName ( ) => s_name ;
@@ -39,36 +41,28 @@ protected override IReadOnlyList<MethodBodyStatement> BuildAttributes()
3941 var attributeType = new CSharpType ( typeof ( ModelReaderWriterBuildableAttribute ) ) ;
4042 var attributeStatement = new AttributeStatement ( attributeType , TypeOf ( buildableType . Key ) ) ;
4143
42- // If the type is experimental, we add a suppression for it
43- string justification = $ "{ buildableType . Key } is experimental and may change in future versions.";
44+ string experimentalTypeJustification = $ "{ buildableType . Key } is experimental and may change in future versions.";
45+ string obsoleteTypeJustification = $ "{ buildableType . Key } is obsolete and may be removed in future versions.";
46+
4447 if ( buildableType . Value is not null )
4548 {
46- var experimentalAttribute =
47- buildableType . Value . CanonicalView . Attributes . FirstOrDefault ( a => a . Type . Equals ( typeof ( ExperimentalAttribute ) ) ) ;
48- if ( experimentalAttribute != null )
49- {
50- var key = experimentalAttribute . Arguments [ 0 ] ;
51- attributes . Add ( new SuppressionStatement ( attributeStatement , key , justification ) ) ;
52- }
53- else
54- {
55- attributes . Add ( attributeStatement ) ;
56- }
49+ // If the type is experimental or obsolete, we add a suppression for it
50+ AddAttributeForType (
51+ attributes ,
52+ attributeStatement ,
53+ buildableType . Value ,
54+ experimentalTypeJustification ,
55+ obsoleteTypeJustification ) ;
5756 }
5857 // A dependency model - need to use reflection to get the attribute data
5958 else if ( buildableType . Key . IsFrameworkType )
6059 {
61- var experimentalAttr = buildableType . Key . FrameworkType . GetCustomAttributes ( typeof ( ExperimentalAttribute ) , false )
62- . FirstOrDefault ( ) ;
63- if ( experimentalAttr != null )
64- {
65- var key = experimentalAttr . GetType ( ) . GetProperty ( "DiagnosticId" ) ? . GetValue ( experimentalAttr ) ;
66- attributes . Add ( new SuppressionStatement ( attributeStatement , Literal ( key ) , justification ) ) ;
67- }
68- else
69- {
70- attributes . Add ( attributeStatement ) ;
71- }
60+ AddAttributeForType (
61+ attributes ,
62+ attributeStatement ,
63+ buildableType . Key . FrameworkType ,
64+ experimentalTypeJustification ,
65+ obsoleteTypeJustification ) ;
7266 }
7367 }
7468
@@ -175,8 +169,7 @@ private void CollectBuildableTypesFromFrameworkType(
175169 {
176170 var propertyType = property . PropertyType ;
177171
178- // Handle generic types by getting their concrete types if available
179- if ( propertyType . IsGenericTypeDefinition && frameworkType . Arguments . Count > 0 )
172+ if ( ! propertyType . IsVisible || propertyType . IsGenericTypeDefinition && frameworkType . Arguments . Count > 0 )
180173 {
181174 continue ;
182175 }
@@ -285,6 +278,59 @@ private static bool ImplementsModelReaderWriter(TypeProvider typeProvider)
285278 return false ;
286279 }
287280
281+ private static void AddAttributeForType (
282+ List < MethodBodyStatement > attributes ,
283+ AttributeStatement attributeStatement ,
284+ TypeProvider typeProvider ,
285+ string experimentalTypeJustification ,
286+ string obsoleteTypeJustification )
287+ {
288+ AttributeStatement ? experimentalOrObsoleteAttribute = typeProvider . CanonicalView . Attributes
289+ . FirstOrDefault ( a => a . Type . Equals ( typeof ( ExperimentalAttribute ) ) || a . Type . Equals ( typeof ( ObsoleteAttribute ) ) ) ;
290+
291+ if ( experimentalOrObsoleteAttribute ? . Type . Equals ( typeof ( ExperimentalAttribute ) ) == true )
292+ {
293+ attributes . Add ( new SuppressionStatement ( attributeStatement , experimentalOrObsoleteAttribute . Arguments [ 0 ] , experimentalTypeJustification ) ) ;
294+ }
295+ else if ( experimentalOrObsoleteAttribute ? . Type . Equals ( typeof ( ObsoleteAttribute ) ) == true )
296+ {
297+ attributes . Add ( new SuppressionStatement ( attributeStatement , Literal ( DefaultObsoleteDiagnosticId ) , obsoleteTypeJustification ) ) ;
298+ }
299+ else
300+ {
301+ attributes . Add ( attributeStatement ) ;
302+ }
303+ }
304+
305+ private static void AddAttributeForType (
306+ List < MethodBodyStatement > attributes ,
307+ AttributeStatement attributeStatement ,
308+ Type frameworkType ,
309+ string experimentalTypeJustification ,
310+ string obsoleteTypeJustification )
311+ {
312+ var experimentalAttr = frameworkType . GetCustomAttributes ( typeof ( ExperimentalAttribute ) , false )
313+ . FirstOrDefault ( ) ;
314+ if ( experimentalAttr != null )
315+ {
316+ var key = experimentalAttr . GetType ( ) . GetProperty ( "DiagnosticId" ) ? . GetValue ( experimentalAttr ) ;
317+ attributes . Add ( new SuppressionStatement ( attributeStatement , Literal ( key ) , experimentalTypeJustification ) ) ;
318+ return ;
319+ }
320+
321+ var obsoleteAttr = frameworkType . GetCustomAttributes ( typeof ( ObsoleteAttribute ) , false )
322+ . FirstOrDefault ( ) ;
323+ if ( obsoleteAttr != null )
324+ {
325+ var key = obsoleteAttr . GetType ( ) . GetProperty ( "DiagnosticId" ) ? . GetValue ( obsoleteAttr )
326+ ?? DefaultObsoleteDiagnosticId ;
327+ attributes . Add ( new SuppressionStatement ( attributeStatement , Literal ( key ) , obsoleteTypeJustification ) ) ;
328+ return ;
329+ }
330+
331+ attributes . Add ( attributeStatement ) ;
332+ }
333+
288334 private static bool IsModelReaderWriterInterfaceType ( CSharpType type )
289335 {
290336 return type . Name . StartsWith ( "IPersistableModel" ) || type . Name . StartsWith ( "IJsonModel" ) ;
0 commit comments