@@ -277,6 +277,7 @@ interface BaseMethodOpts {
277277
278278interface BaseMethodEmitOpts {
279279 renderAbstract ?: boolean ;
280+ forceEmitBody ?: boolean ;
280281}
281282
282283abstract class BaseMethod implements PythonBase {
@@ -285,10 +286,11 @@ abstract class BaseMethod implements PythonBase {
285286 public readonly abstract : boolean ;
286287
287288 protected readonly abstract implicitParameter : string ;
288- protected readonly jsiiMethod ? : string ;
289+ protected readonly jsiiMethod : string ;
289290 protected readonly decorator ?: string ;
290291 protected readonly classAsFirstParameter : boolean = false ;
291292 protected readonly returnFromJSIIMethod : boolean = true ;
293+ protected readonly shouldEmitBody : boolean = true ;
292294
293295 private readonly jsName ?: string ;
294296 private readonly parameters : spec . Parameter [ ] ;
@@ -313,7 +315,7 @@ abstract class BaseMethod implements PythonBase {
313315 }
314316
315317 public emit ( code : CodeMaker , resolver : TypeResolver , opts ?: BaseMethodEmitOpts ) {
316- const { renderAbstract = true } = opts || { } ;
318+ const { renderAbstract = true , forceEmitBody = false } = opts || { } ;
317319
318320 let returnType : string ;
319321 if ( this . returns !== undefined ) {
@@ -420,12 +422,12 @@ abstract class BaseMethod implements PythonBase {
420422 }
421423
422424 code . openBlock ( `def ${ this . name } (${ pythonParams . join ( ", " ) } ) -> ${ returnType } ` ) ;
423- this . emitBody ( code , resolver , renderAbstract ) ;
425+ this . emitBody ( code , resolver , renderAbstract , forceEmitBody ) ;
424426 code . closeBlock ( ) ;
425427 }
426428
427- private emitBody ( code : CodeMaker , resolver : TypeResolver , renderAbstract : boolean ) {
428- if ( this . jsiiMethod === undefined || ( renderAbstract && this . abstract ) ) {
429+ private emitBody ( code : CodeMaker , resolver : TypeResolver , renderAbstract : boolean , forceEmitBody : boolean ) {
430+ if ( ( ! this . shouldEmitBody && ! forceEmitBody ) || ( renderAbstract && this . abstract ) ) {
429431 code . line ( "..." ) ;
430432 } else {
431433 if ( this . liftedProp !== undefined ) {
@@ -498,6 +500,7 @@ interface BasePropertyOpts {
498500
499501interface BasePropertyEmitOpts {
500502 renderAbstract ?: boolean ;
503+ forceEmitBody ?: boolean ;
501504}
502505
503506abstract class BaseProperty implements PythonBase {
@@ -507,8 +510,9 @@ abstract class BaseProperty implements PythonBase {
507510
508511 protected readonly abstract decorator : string ;
509512 protected readonly abstract implicitParameter : string ;
510- protected readonly jsiiGetMethod ?: string ;
511- protected readonly jsiiSetMethod ?: string ;
513+ protected readonly jsiiGetMethod : string ;
514+ protected readonly jsiiSetMethod : string ;
515+ protected readonly shouldEmitBody : boolean = true ;
512516
513517 private readonly jsName : string ;
514518 private readonly type : spec . TypeReference ;
@@ -528,7 +532,7 @@ abstract class BaseProperty implements PythonBase {
528532 }
529533
530534 public emit ( code : CodeMaker , resolver : TypeResolver , opts ?: BasePropertyEmitOpts ) {
531- const { renderAbstract = true } = opts || { } ;
535+ const { renderAbstract = true , forceEmitBody = false } = opts || { } ;
532536 const pythonType = resolver . resolve ( this . type , { forwardReferences : false } ) ;
533537
534538 code . line ( `@${ this . decorator } ` ) ;
@@ -537,7 +541,7 @@ abstract class BaseProperty implements PythonBase {
537541 code . line ( "@abc.abstractmethod" ) ;
538542 }
539543 code . openBlock ( `def ${ this . name } (${ this . implicitParameter } ) -> ${ pythonType } ` ) ;
540- if ( this . jsiiGetMethod !== undefined && ( ! renderAbstract || ! this . abstract ) ) {
544+ if ( ( this . shouldEmitBody || forceEmitBody ) && ( ! renderAbstract || ! this . abstract ) ) {
541545 code . line ( `return jsii.${ this . jsiiGetMethod } (${ this . implicitParameter } , "${ this . jsName } ")` ) ;
542546 } else {
543547 code . line ( "..." ) ;
@@ -550,7 +554,7 @@ abstract class BaseProperty implements PythonBase {
550554 code . line ( "@abc.abstractmethod" ) ;
551555 }
552556 code . openBlock ( `def ${ this . name } (${ this . implicitParameter } , value: ${ pythonType } )` ) ;
553- if ( this . jsiiSetMethod !== undefined && ( ! renderAbstract || ! this . abstract ) ) {
557+ if ( ( this . shouldEmitBody || forceEmitBody ) && ( ! renderAbstract || ! this . abstract ) ) {
554558 code . line ( `return jsii.${ this . jsiiSetMethod } (${ this . implicitParameter } , "${ this . jsName } ", value)` ) ;
555559 } else {
556560 code . line ( "..." ) ;
@@ -562,6 +566,29 @@ abstract class BaseProperty implements PythonBase {
562566
563567class Interface extends BasePythonClassType {
564568
569+ public emit ( code : CodeMaker , resolver : TypeResolver ) {
570+ code . line ( `@jsii.interface(jsii_type="${ this . fqn } ")` ) ;
571+
572+ // First we do our normal class logic for emitting our members.
573+ super . emit ( code , resolver ) ;
574+
575+ // Then, we have to emit a Proxy class which implements our proxy interface.
576+ resolver = this . fqn ? resolver . bind ( this . fqn ) : resolver ;
577+ const proxyBases : string [ ] = this . bases . map ( b => `jsii.proxy_for(${ resolver . resolve ( b ) } )` ) ;
578+ code . openBlock ( `class ${ this . getProxyClassName ( ) } (${ proxyBases . join ( ", " ) } )` ) ;
579+ code . line ( `__jsii_type__ = "${ this . fqn } "` ) ;
580+
581+ if ( this . members . length > 0 ) {
582+ for ( const member of this . members ) {
583+ member . emit ( code , resolver , { forceEmitBody : true } ) ;
584+ }
585+ } else {
586+ code . line ( "pass" ) ;
587+ }
588+
589+ code . closeBlock ( ) ;
590+ }
591+
565592 protected getClassParams ( resolver : TypeResolver ) : string [ ] {
566593 const params : string [ ] = this . bases . map ( b => resolver . resolve ( b ) ) ;
567594
@@ -570,15 +597,31 @@ class Interface extends BasePythonClassType {
570597 return params ;
571598 }
572599
600+ protected emitPreamble ( code : CodeMaker , _resolver : TypeResolver ) {
601+ code . line ( "@staticmethod" ) ;
602+ code . openBlock ( "def __jsii_proxy_class__()" ) ;
603+ code . line ( `return ${ this . getProxyClassName ( ) } ` ) ;
604+ code . closeBlock ( ) ;
605+ }
606+
607+ private getProxyClassName ( ) : string {
608+ return `_${ this . name } Proxy` ;
609+ }
610+
573611}
574612
575613class InterfaceMethod extends BaseMethod {
576614 protected readonly implicitParameter : string = "self" ;
615+ protected readonly jsiiMethod : string = "invoke" ;
616+ protected readonly shouldEmitBody : boolean = false ;
577617}
578618
579619class InterfaceProperty extends BaseProperty {
580620 protected readonly decorator : string = "property" ;
581621 protected readonly implicitParameter : string = "self" ;
622+ protected readonly jsiiGetMethod : string = "get" ;
623+ protected readonly jsiiSetMethod : string = "set" ;
624+ protected readonly shouldEmitBody : boolean = false ;
582625}
583626
584627class TypedDict extends BasePythonClassType {
0 commit comments