@@ -25,6 +25,8 @@ import {
2525 refTypeName ,
2626 isRpcMethod ,
2727 isNodeFullyExperimental ,
28+ isNodeFullyDeprecated ,
29+ isSchemaDeprecated ,
2830 isObjectSchema ,
2931 isVoidSchema ,
3032 REPO_ROOT ,
@@ -316,14 +318,15 @@ let generatedEnums = new Map<string, { enumName: string; values: string[] }>();
316318/** Schema definitions available during session event generation (for $ref resolution). */
317319let sessionDefinitions : DefinitionCollections = { definitions : { } , $defs : { } } ;
318320
319- function getOrCreateEnum ( parentClassName : string , propName : string , values : string [ ] , enumOutput : string [ ] , description ?: string , explicitName ?: string ) : string {
321+ function getOrCreateEnum ( parentClassName : string , propName : string , values : string [ ] , enumOutput : string [ ] , description ?: string , explicitName ?: string , deprecated ?: boolean ) : string {
320322 const enumName = explicitName ?? `${ parentClassName } ${ propName } ` ;
321323 const existing = generatedEnums . get ( enumName ) ;
322324 if ( existing ) return existing . enumName ;
323325 generatedEnums . set ( enumName , { enumName, values } ) ;
324326
325327 const lines : string [ ] = [ ] ;
326328 lines . push ( ...xmlDocEnumComment ( description , "" ) ) ;
329+ if ( deprecated ) lines . push ( `[Obsolete]` ) ;
327330 lines . push ( `[JsonConverter(typeof(JsonStringEnumConverter<${ enumName } >))]` , `public enum ${ enumName } ` , `{` ) ;
328331 for ( const value of values ) {
329332 lines . push ( ` /// <summary>The <c>${ escapeXml ( value ) } </c> variant.</summary>` ) ;
@@ -458,6 +461,7 @@ function generateDerivedClass(
458461 const required = new Set ( schema . required || [ ] ) ;
459462
460463 lines . push ( ...xmlDocCommentWithFallback ( schema . description , `The <c>${ escapeXml ( discriminatorValue ) } </c> variant of <see cref="${ baseClassName } "/>.` , "" ) ) ;
464+ if ( isSchemaDeprecated ( schema ) ) lines . push ( `[Obsolete]` ) ;
461465 lines . push ( `public partial class ${ className } : ${ baseClassName } ` ) ;
462466 lines . push ( `{` ) ;
463467 lines . push ( ` /// <inheritdoc />` ) ;
@@ -476,6 +480,7 @@ function generateDerivedClass(
476480
477481 lines . push ( ...xmlDocPropertyComment ( ( propSchema as JSONSchema7 ) . description , propName , " " ) ) ;
478482 lines . push ( ...emitDataAnnotations ( propSchema as JSONSchema7 , " " ) ) ;
483+ if ( isSchemaDeprecated ( propSchema as JSONSchema7 ) ) lines . push ( ` [Obsolete]` ) ;
479484 if ( isDurationProperty ( propSchema as JSONSchema7 ) ) lines . push ( ` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]` ) ;
480485 if ( ! isReq ) lines . push ( ` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]` ) ;
481486 lines . push ( ` [JsonPropertyName("${ propName } ")]` ) ;
@@ -499,6 +504,7 @@ function generateNestedClass(
499504 const required = new Set ( schema . required || [ ] ) ;
500505 const lines : string [ ] = [ ] ;
501506 lines . push ( ...xmlDocCommentWithFallback ( schema . description , `Nested data type for <c>${ className } </c>.` , "" ) ) ;
507+ if ( isSchemaDeprecated ( schema ) ) lines . push ( `[Obsolete]` ) ;
502508 lines . push ( `public partial class ${ className } ` , `{` ) ;
503509
504510 for ( const [ propName , propSchema ] of Object . entries ( schema . properties || { } ) ) {
@@ -510,6 +516,7 @@ function generateNestedClass(
510516
511517 lines . push ( ...xmlDocPropertyComment ( prop . description , propName , " " ) ) ;
512518 lines . push ( ...emitDataAnnotations ( prop , " " ) ) ;
519+ if ( isSchemaDeprecated ( prop ) ) lines . push ( ` [Obsolete]` ) ;
513520 if ( isDurationProperty ( prop ) ) lines . push ( ` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]` ) ;
514521 if ( ! isReq ) lines . push ( ` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]` ) ;
515522 lines . push ( ` [JsonPropertyName("${ propName } ")]` ) ;
@@ -539,7 +546,7 @@ function resolveSessionPropertyType(
539546 }
540547
541548 if ( refSchema . enum && Array . isArray ( refSchema . enum ) ) {
542- const enumName = getOrCreateEnum ( className , "" , refSchema . enum as string [ ] , enumOutput , refSchema . description ) ;
549+ const enumName = getOrCreateEnum ( className , "" , refSchema . enum as string [ ] , enumOutput , refSchema . description , undefined , isSchemaDeprecated ( refSchema ) ) ;
543550 return isRequired ? enumName : `${ enumName } ?` ;
544551 }
545552
@@ -573,7 +580,7 @@ function resolveSessionPropertyType(
573580 return hasNull || ! isRequired ? "object?" : "object" ;
574581 }
575582 if ( propSchema . enum && Array . isArray ( propSchema . enum ) ) {
576- const enumName = getOrCreateEnum ( parentClassName , propName , propSchema . enum as string [ ] , enumOutput , propSchema . description , propSchema . title as string | undefined ) ;
583+ const enumName = getOrCreateEnum ( parentClassName , propName , propSchema . enum as string [ ] , enumOutput , propSchema . description , propSchema . title as string | undefined , isSchemaDeprecated ( propSchema ) ) ;
577584 return isRequired ? enumName : `${ enumName } ?` ;
578585 }
579586 if ( propSchema . type === "object" && propSchema . properties ) {
@@ -607,6 +614,9 @@ function generateDataClass(variant: EventVariant, knownTypes: Map<string, string
607614 } else {
608615 lines . push ( ...rawXmlDocSummary ( `Event payload for <see cref="${ variant . className } "/>.` , "" ) ) ;
609616 }
617+ if ( isSchemaDeprecated ( variant . dataSchema ) ) {
618+ lines . push ( `[Obsolete]` ) ;
619+ }
610620 lines . push ( `public partial class ${ variant . dataClassName } ` , `{` ) ;
611621
612622 for ( const [ propName , propSchema ] of Object . entries ( variant . dataSchema . properties ) ) {
@@ -617,6 +627,7 @@ function generateDataClass(variant: EventVariant, knownTypes: Map<string, string
617627
618628 lines . push ( ...xmlDocPropertyComment ( ( propSchema as JSONSchema7 ) . description , propName , " " ) ) ;
619629 lines . push ( ...emitDataAnnotations ( propSchema as JSONSchema7 , " " ) ) ;
630+ if ( isSchemaDeprecated ( propSchema as JSONSchema7 ) ) lines . push ( ` [Obsolete]` ) ;
620631 if ( isDurationProperty ( propSchema as JSONSchema7 ) ) lines . push ( ` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]` ) ;
621632 if ( ! isReq ) lines . push ( ` [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]` ) ;
622633 lines . push ( ` [JsonPropertyName("${ propName } ")]` ) ;
@@ -659,6 +670,9 @@ function generateSessionEventsCode(schema: JSONSchema7): string {
659670// AUTO-GENERATED FILE - DO NOT EDIT
660671// Generated from: session-events.schema.json
661672
673+ #pragma warning disable CS0612 // Type or member is obsolete
674+ #pragma warning disable CS0618 // Type or member is obsolete (with message)
675+
662676using System.ComponentModel.DataAnnotations;
663677using System.Diagnostics;
664678using System.Diagnostics.CodeAnalysis;
@@ -806,7 +820,7 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam
806820 }
807821
808822 if ( refSchema . enum && Array . isArray ( refSchema . enum ) ) {
809- const enumName = getOrCreateEnum ( typeName , "" , refSchema . enum as string [ ] , rpcEnumOutput , refSchema . description ) ;
823+ const enumName = getOrCreateEnum ( typeName , "" , refSchema . enum as string [ ] , rpcEnumOutput , refSchema . description , undefined , isSchemaDeprecated ( refSchema ) ) ;
810824 return isRequired ? enumName : `${ enumName } ?` ;
811825 }
812826
@@ -835,6 +849,7 @@ function resolveRpcType(schema: JSONSchema7, isRequired: boolean, parentClassNam
835849 rpcEnumOutput ,
836850 schema . description ,
837851 schema . title as string | undefined ,
852+ isSchemaDeprecated ( schema ) ,
838853 ) ;
839854 return isRequired ? enumName : `${ enumName } ?` ;
840855 }
@@ -890,6 +905,9 @@ function emitRpcClass(
890905 if ( experimentalRpcTypes . has ( className ) ) {
891906 lines . push ( `[Experimental(Diagnostics.Experimental)]` ) ;
892907 }
908+ if ( isSchemaDeprecated ( schema ) || isSchemaDeprecated ( effectiveSchema ) ) {
909+ lines . push ( `[Obsolete]` ) ;
910+ }
893911 lines . push ( `${ visibility } sealed class ${ className } ` , `{` ) ;
894912
895913 const props = Object . entries ( effectiveSchema . properties || { } ) ;
@@ -903,6 +921,7 @@ function emitRpcClass(
903921
904922 lines . push ( ...xmlDocPropertyComment ( prop . description , propName , " " ) ) ;
905923 lines . push ( ...emitDataAnnotations ( prop , " " ) ) ;
924+ if ( isSchemaDeprecated ( prop ) ) lines . push ( ` [Obsolete]` ) ;
906925 if ( isDurationProperty ( prop ) ) lines . push ( ` [JsonConverter(typeof(MillisecondsTimeSpanConverter))]` ) ;
907926 lines . push ( ` [JsonPropertyName("${ propName } ")]` ) ;
908927
@@ -934,7 +953,7 @@ function emitRpcClass(
934953 */
935954function emitNonObjectResultType ( typeName : string , schema : JSONSchema7 , classes : string [ ] ) : string {
936955 if ( schema . enum && Array . isArray ( schema . enum ) ) {
937- const enumName = getOrCreateEnum ( "" , typeName , schema . enum as string [ ] , rpcEnumOutput , schema . description , typeName ) ;
956+ const enumName = getOrCreateEnum ( "" , typeName , schema . enum as string [ ] , rpcEnumOutput , schema . description , typeName , isSchemaDeprecated ( schema ) ) ;
938957 emittedRpcEnumResultTypes . add ( enumName ) ;
939958 return enumName ;
940959 }
@@ -971,7 +990,7 @@ function emitServerRpcClasses(node: Record<string, unknown>, classes: string[]):
971990 // Top-level methods (like ping)
972991 for ( const [ key , value ] of topLevelMethods ) {
973992 if ( ! isRpcMethod ( value ) ) continue ;
974- emitServerInstanceMethod ( key , value , srLines , classes , " " , false ) ;
993+ emitServerInstanceMethod ( key , value , srLines , classes , " " , false , false ) ;
975994 }
976995
977996 // Group properties
@@ -1000,9 +1019,13 @@ function emitServerApiClass(className: string, node: Record<string, unknown>, cl
10001019
10011020 lines . push ( `/// <summary>Provides server-scoped ${ displayName } APIs.</summary>` ) ;
10021021 const groupExperimental = isNodeFullyExperimental ( node ) ;
1022+ const groupDeprecated = isNodeFullyDeprecated ( node ) ;
10031023 if ( groupExperimental ) {
10041024 lines . push ( `[Experimental(Diagnostics.Experimental)]` ) ;
10051025 }
1026+ if ( groupDeprecated ) {
1027+ lines . push ( `[Obsolete]` ) ;
1028+ }
10061029 lines . push ( `public sealed class ${ className } ` ) ;
10071030 lines . push ( `{` ) ;
10081031 lines . push ( ` private readonly JsonRpc _rpc;` ) ;
@@ -1018,7 +1041,7 @@ function emitServerApiClass(className: string, node: Record<string, unknown>, cl
10181041
10191042 for ( const [ key , value ] of Object . entries ( node ) ) {
10201043 if ( ! isRpcMethod ( value ) ) continue ;
1021- emitServerInstanceMethod ( key , value , lines , classes , " " , groupExperimental ) ;
1044+ emitServerInstanceMethod ( key , value , lines , classes , " " , groupExperimental , groupDeprecated ) ;
10221045 }
10231046
10241047 for ( const [ subGroupName ] of subGroups ) {
@@ -1045,7 +1068,8 @@ function emitServerInstanceMethod(
10451068 lines : string [ ] ,
10461069 classes : string [ ] ,
10471070 indent : string ,
1048- groupExperimental : boolean
1071+ groupExperimental : boolean ,
1072+ groupDeprecated : boolean
10491073) : void {
10501074 const methodName = toPascalCase ( name ) ;
10511075 const resultSchema = getMethodResultSchema ( method ) ;
@@ -1079,6 +1103,9 @@ function emitServerInstanceMethod(
10791103 if ( method . stability === "experimental" && ! groupExperimental ) {
10801104 lines . push ( `${ indent } [Experimental(Diagnostics.Experimental)]` ) ;
10811105 }
1106+ if ( method . deprecated && ! groupDeprecated ) {
1107+ lines . push ( `${ indent } [Obsolete]` ) ;
1108+ }
10821109
10831110 const sigParams : string [ ] = [ ] ;
10841111 const bodyAssignments : string [ ] = [ ] ;
@@ -1129,7 +1156,7 @@ function emitSessionRpcClasses(node: Record<string, unknown>, classes: string[])
11291156 // Emit top-level session RPC methods directly on the SessionRpc class
11301157 const topLevelLines : string [ ] = [ ] ;
11311158 for ( const [ key , value ] of topLevelMethods ) {
1132- emitSessionMethod ( key , value as RpcMethod , topLevelLines , classes , " " , false ) ;
1159+ emitSessionMethod ( key , value as RpcMethod , topLevelLines , classes , " " , false , false ) ;
11331160 }
11341161 srLines . push ( ...topLevelLines ) ;
11351162
@@ -1142,7 +1169,7 @@ function emitSessionRpcClasses(node: Record<string, unknown>, classes: string[])
11421169 return result ;
11431170}
11441171
1145- function emitSessionMethod ( key : string , method : RpcMethod , lines : string [ ] , classes : string [ ] , indent : string , groupExperimental : boolean ) : void {
1172+ function emitSessionMethod ( key : string , method : RpcMethod , lines : string [ ] , classes : string [ ] , indent : string , groupExperimental : boolean , groupDeprecated : boolean ) : void {
11461173 const methodName = toPascalCase ( key ) ;
11471174 const resultSchema = getMethodResultSchema ( method ) ;
11481175 let resultClassName = ! isVoidSchema ( resultSchema ) ? resultTypeName ( method ) : "" ;
@@ -1180,6 +1207,9 @@ function emitSessionMethod(key: string, method: RpcMethod, lines: string[], clas
11801207 if ( method . stability === "experimental" && ! groupExperimental ) {
11811208 lines . push ( `${ indent } [Experimental(Diagnostics.Experimental)]` ) ;
11821209 }
1210+ if ( method . deprecated && ! groupDeprecated ) {
1211+ lines . push ( `${ indent } [Obsolete]` ) ;
1212+ }
11831213 const sigParams : string [ ] = [ ] ;
11841214 const bodyAssignments = [ `SessionId = _sessionId` ] ;
11851215
@@ -1206,10 +1236,12 @@ function emitSessionApiClass(className: string, node: Record<string, unknown>, c
12061236 const parts : string [ ] = [ ] ;
12071237 const displayName = className . replace ( / A p i $ / , "" ) ;
12081238 const groupExperimental = isNodeFullyExperimental ( node ) ;
1239+ const groupDeprecated = isNodeFullyDeprecated ( node ) ;
12091240 const experimentalAttr = groupExperimental ? `[Experimental(Diagnostics.Experimental)]\n` : "" ;
1241+ const deprecatedAttr = groupDeprecated ? `[Obsolete]\n` : "" ;
12101242 const subGroups = Object . entries ( node ) . filter ( ( [ , v ] ) => typeof v === "object" && v !== null && ! isRpcMethod ( v ) ) ;
12111243
1212- const lines = [ `/// <summary>Provides session-scoped ${ displayName } APIs.</summary>` , `${ experimentalAttr } public sealed class ${ className } ` , `{` , ` private readonly JsonRpc _rpc;` , ` private readonly string _sessionId;` , "" ] ;
1244+ const lines = [ `/// <summary>Provides session-scoped ${ displayName } APIs.</summary>` , `${ experimentalAttr } ${ deprecatedAttr } public sealed class ${ className } ` , `{` , ` private readonly JsonRpc _rpc;` , ` private readonly string _sessionId;` , "" ] ;
12131245 lines . push ( ` internal ${ className } (JsonRpc rpc, string sessionId)` , ` {` , ` _rpc = rpc;` , ` _sessionId = sessionId;` ) ;
12141246 for ( const [ subGroupName ] of subGroups ) {
12151247 const subClassName = className . replace ( / A p i $ / , "" ) + toPascalCase ( subGroupName ) + "Api" ;
@@ -1219,7 +1251,7 @@ function emitSessionApiClass(className: string, node: Record<string, unknown>, c
12191251
12201252 for ( const [ key , value ] of Object . entries ( node ) ) {
12211253 if ( ! isRpcMethod ( value ) ) continue ;
1222- emitSessionMethod ( key , value , lines , classes , " " , groupExperimental ) ;
1254+ emitSessionMethod ( key , value , lines , classes , " " , groupExperimental , groupDeprecated ) ;
12231255 }
12241256
12251257 for ( const [ subGroupName ] of subGroups ) {
@@ -1290,10 +1322,14 @@ function emitClientSessionApiRegistration(clientSchema: Record<string, unknown>,
12901322 for ( const { groupName, groupNode, methods } of groups ) {
12911323 const interfaceName = clientHandlerInterfaceName ( groupName ) ;
12921324 const groupExperimental = isNodeFullyExperimental ( groupNode ) ;
1325+ const groupDeprecated = isNodeFullyDeprecated ( groupNode ) ;
12931326 lines . push ( `/// <summary>Handles \`${ groupName } \` client session API methods.</summary>` ) ;
12941327 if ( groupExperimental ) {
12951328 lines . push ( `[Experimental(Diagnostics.Experimental)]` ) ;
12961329 }
1330+ if ( groupDeprecated ) {
1331+ lines . push ( `[Obsolete]` ) ;
1332+ }
12971333 lines . push ( `public interface ${ interfaceName } ` ) ;
12981334 lines . push ( `{` ) ;
12991335 for ( const method of methods ) {
@@ -1305,6 +1341,9 @@ function emitClientSessionApiRegistration(clientSchema: Record<string, unknown>,
13051341 if ( method . stability === "experimental" && ! groupExperimental ) {
13061342 lines . push ( ` [Experimental(Diagnostics.Experimental)]` ) ;
13071343 }
1344+ if ( method . deprecated && ! groupDeprecated ) {
1345+ lines . push ( ` [Obsolete]` ) ;
1346+ }
13081347 if ( hasParams ) {
13091348 lines . push ( ` ${ taskType } ${ clientHandlerMethodName ( method . rpcMethod ) } (${ paramsTypeName ( method ) } request, CancellationToken cancellationToken = default);` ) ;
13101349 } else {
@@ -1400,6 +1439,9 @@ function generateRpcCode(schema: ApiSchema): string {
14001439// AUTO-GENERATED FILE - DO NOT EDIT
14011440// Generated from: api.schema.json
14021441
1442+ #pragma warning disable CS0612 // Type or member is obsolete
1443+ #pragma warning disable CS0618 // Type or member is obsolete (with message)
1444+
14031445using System.ComponentModel.DataAnnotations;
14041446using System.Diagnostics.CodeAnalysis;
14051447using System.Text.Json;
0 commit comments