@@ -63,6 +63,7 @@ import {
63
63
} from "./boilerplate.js" ;
64
64
import { getProjectDocs } from "./doc.js" ;
65
65
import {
66
+ Attribute ,
66
67
CSharpSourceType ,
67
68
CSharpType ,
68
69
CSharpTypeMetadata ,
@@ -554,7 +555,12 @@ export async function $onEmit(context: EmitContext<CSharpServiceEmitterOptions>)
554
555
nullableType : nullable ,
555
556
} = this . #findPropertyType( property ) ;
556
557
const doc = getDoc ( this . emitter . getProgram ( ) , property ) ;
557
- const attributes = getModelAttributes ( this . emitter . getProgram ( ) , property , propertyName ) ;
558
+ const attributes = new Map < string , Attribute > (
559
+ getModelAttributes ( this . emitter . getProgram ( ) , property , propertyName ) . map ( ( a ) => [
560
+ a . type . name ,
561
+ a ,
562
+ ] ) ,
563
+ ) ;
558
564
const modelName : string | undefined = this . emitter . getContext ( ) [ "name" ] ;
559
565
if (
560
566
modelName === propertyName ||
@@ -563,15 +569,15 @@ export async function $onEmit(context: EmitContext<CSharpServiceEmitterOptions>)
563
569
isErrorModel ( this . emitter . getProgram ( ) , property . model ) )
564
570
) {
565
571
propertyName = `${ propertyName } Prop` ;
566
- attributes . push (
567
- getEncodedNameAttribute ( this . emitter . getProgram ( ) , property , propertyName ) ! ,
568
- ) ;
572
+ const attr = getEncodedNameAttribute ( this . emitter . getProgram ( ) , property , propertyName ) ! ;
573
+ if ( ! attributes . has ( attr . type . name ) ) attributes . set ( attr . type . name , attr ) ;
569
574
}
570
575
const defaultValue = property . defaultValue
571
576
? code `${ JSON . stringify ( serializeValueAsJson ( this . emitter . getProgram ( ) , property . defaultValue , property ) ) } `
572
577
: typeDefault ;
578
+ const attributeList = [ ...attributes . values ( ) ] ;
573
579
return this . emitter . result
574
- . rawCode ( code `${ doc ? `${ formatComment ( doc ) } \n` : "" } ${ `${ attributes . map ( ( attribute ) => attribute . getApplicationString ( this . emitter . getContext ( ) . scope ) ) . join ( "\n" ) } ${ attributes ?. length > 0 ? "\n" : "" } ` } public ${ this . #isInheritedProperty( property ) ? "new " : "" } ${ typeName } ${
580
+ . rawCode ( code `${ doc ? `${ formatComment ( doc ) } \n` : "" } ${ `${ attributeList . map ( ( attribute ) => attribute . getApplicationString ( this . emitter . getContext ( ) . scope ) ) . join ( "\n" ) } ${ attributeList ?. length > 0 ? "\n" : "" } ` } public ${ this . #isInheritedProperty( property ) ? "new " : "" } ${ typeName } ${
575
581
isValueType ( this . emitter . getProgram ( ) , property . type ) && ( property . optional || nullable )
576
582
? "?"
577
583
: ""
@@ -658,7 +664,6 @@ export async function $onEmit(context: EmitContext<CSharpServiceEmitterOptions>)
658
664
interfaceDeclarationOperations ( iface : Interface ) : EmitterOutput < string > {
659
665
// add in operations
660
666
const builder : StringBuilder = new StringBuilder ( ) ;
661
- const metadata = new HttpMetadata ( ) ;
662
667
const context = this . emitter . getContext ( ) ;
663
668
const name = `${ ensureCSharpIdentifier (
664
669
this . emitter . getProgram ( ) ,
@@ -682,9 +687,8 @@ export async function $onEmit(context: EmitContext<CSharpServiceEmitterOptions>)
682
687
for ( const response of httpOp . responses . filter (
683
688
( r ) => ! isErrorModel ( this . emitter . getProgram ( ) , r . type ) ,
684
689
) ) {
685
- returnTypes . push (
686
- metadata . resolveLogicalResponseType ( this . emitter . getProgram ( ) , response ) ,
687
- ) ;
690
+ const [ _ , responseType ] = this . #resolveOperationResponse( response , httpOp . operation ) ;
691
+ returnTypes . push ( responseType ) ;
688
692
}
689
693
const returnInfo = coalesceTypes ( this . emitter . getProgram ( ) , returnTypes , namespace ) ;
690
694
const returnType : CSharpType = returnInfo ?. type || UnknownType ;
@@ -878,6 +882,32 @@ export async function $onEmit(context: EmitContext<CSharpServiceEmitterOptions>)
878
882
return this . emitter . result . rawCode ( stringTemplate . stringValue || "" ) ;
879
883
}
880
884
885
+ #resolveOperationResponse(
886
+ response : HttpOperationResponse ,
887
+ operation : Operation ,
888
+ ) : [ CSharpType , Type ] {
889
+ function getName ( sourceType : Model , part : string ) : string {
890
+ return ensureCSharpIdentifier ( emitter . getProgram ( ) , sourceType , part , NameCasingType . Class ) ;
891
+ }
892
+ let responseType = new HttpMetadata ( ) . resolveLogicalResponseType (
893
+ this . emitter . getProgram ( ) ,
894
+ response ,
895
+ ) ;
896
+
897
+ if ( responseType . kind === "Model" && ! responseType . name ) {
898
+ const modelName = `${ getName ( responseType , operation . interface ! . name ) } ${ getName ( responseType , operation . name ) } Response}` ;
899
+ const returnedType = this . emitter
900
+ . getProgram ( )
901
+ . checker . cloneType ( responseType , { name : modelName } ) ;
902
+ responseType = returnedType ;
903
+ }
904
+ this . emitter . emitType ( responseType ) ;
905
+
906
+ const context = this . emitter . getContext ( ) ;
907
+ const result = getCSharpType ( this . emitter . getProgram ( ) , responseType , context . namespace ) ;
908
+ return [ result ?. type || UnknownType , responseType ] ;
909
+ }
910
+
881
911
#getOperationResponse( operation : HttpOperation ) : ResponseInfo | undefined {
882
912
const validResponses = operation . responses . filter (
883
913
( r ) =>
@@ -902,46 +932,53 @@ export async function $onEmit(context: EmitContext<CSharpServiceEmitterOptions>)
902
932
} ;
903
933
}
904
934
#emitOperationResponses( operation : HttpOperation ) : EmitterOutput < string > {
935
+ function isValid ( program : Program , response : HttpOperationResponse ) {
936
+ return (
937
+ ! isErrorModel ( program , response . type ) &&
938
+ getCSharpStatusCode ( response . statusCodes ) !== undefined
939
+ ) ;
940
+ }
905
941
const builder : StringBuilder = new StringBuilder ( ) ;
906
942
let i = 0 ;
907
943
const validResponses = operation . responses . filter (
908
944
( r ) =>
909
945
! isErrorModel ( this . emitter . getProgram ( ) , r . type ) &&
910
946
getCSharpStatusCode ( r . statusCodes ) !== undefined ,
911
947
) ;
912
- for ( const response of validResponses ) {
913
- i ++ ;
914
- builder . push ( code `${ this . #emitOperationResponseDecorator( response ) } ` ) ;
915
- if ( i < validResponses . length ) {
916
- builder . pushLiteralSegment ( "\n" ) ;
917
- }
918
- }
919
-
920
948
for ( const response of operation . responses ) {
921
- if ( ! isEmptyResponseModel ( this . emitter . getProgram ( ) , response . type ) )
922
- this . emitter . emitType ( response . type ) ;
949
+ const [ responseType , resolvedResponse ] = this . #resolveOperationResponse(
950
+ response ,
951
+ operation . operation ,
952
+ ) ;
953
+ if ( isValid ( this . emitter . getProgram ( ) , response ) ) {
954
+ i ++ ;
955
+ builder . push (
956
+ code `${ this . #emitOperationResponseDecorator( response , resolvedResponse , responseType ) } ` ,
957
+ ) ;
958
+ if ( i < validResponses . length ) {
959
+ builder . pushLiteralSegment ( "\n" ) ;
960
+ }
961
+ }
923
962
}
924
963
925
964
return builder . reduce ( ) ;
926
965
}
927
966
928
- #emitOperationResponseDecorator( response : HttpOperationResponse ) {
929
- const responseType = new HttpMetadata ( ) . resolveLogicalResponseType (
930
- this . emitter . getProgram ( ) ,
931
- response ,
932
- ) ;
967
+ #emitOperationResponseDecorator(
968
+ response : HttpOperationResponse ,
969
+ responseType : Type ,
970
+ result : CSharpType ,
971
+ ) {
933
972
return this . emitter . result . rawCode (
934
973
code `[ProducesResponseType((int)${ getCSharpStatusCode (
935
974
response . statusCodes ,
936
- ) ! } , Type = typeof(${ this . #emitResponseType( responseType ) } ))]`,
975
+ ) ! } , Type = typeof(${ this . #emitResponseType( result ) } ))]`,
937
976
) ;
938
977
}
939
978
940
- #emitResponseType( type : Type ) {
979
+ #emitResponseType( type : CSharpType ) {
941
980
const context = this . emitter . getContext ( ) ;
942
- const result = getCSharpType ( this . emitter . getProgram ( ) , type , context . namespace ) ;
943
- const resultType = result ?. type || UnknownType ;
944
- return resultType . getTypeReference ( context . scope ) ;
981
+ return type . getTypeReference ( context . scope ) ;
945
982
}
946
983
947
984
unionDeclaration ( union : Union , name : string ) : EmitterOutput < string > {
0 commit comments