@@ -162,14 +162,21 @@ export class Assembler implements Emitter {
162162 *
163163 * @returns the de-referenced type, if it was found, otherwise ``undefined``.
164164 */
165- private _dereference ( ref : spec . NamedTypeReference ) : spec . Type | undefined {
165+ private _dereference ( ref : spec . NamedTypeReference , referencingNode : ts . Node ) : spec . Type | undefined {
166166 const [ assm , ] = ref . fqn . split ( '.' ) ;
167+ let type ;
167168 if ( assm === this . projectInfo . name ) {
168- return this . _types [ ref . fqn ] ;
169+ type = this . _types [ ref . fqn ] ;
169170 } else {
170171 const assembly = this . projectInfo . transitiveDependencies . find ( dep => dep . name === assm ) ;
171- return assembly && assembly . types && assembly . types [ ref . fqn ] ;
172+ type = assembly && assembly . types && assembly . types [ ref . fqn ] ;
172173 }
174+
175+ if ( ! type ) {
176+ this . _diagnostic ( referencingNode , ts . DiagnosticCategory . Error , `Unable to resolve referenced type '${ ref . fqn } '. Missing export?` ) ;
177+ }
178+
179+ return type ;
173180 }
174181
175182 private _diagnostic ( node : ts . Node | null , category : ts . DiagnosticCategory , messageText : string ) {
@@ -206,7 +213,7 @@ export class Assembler implements Emitter {
206213 return `unknown.${ typeName } ` ;
207214 }
208215 const fqn = `${ pkg . name } .${ typeName } ` ;
209- if ( pkg . name !== this . projectInfo . name && ! this . _dereference ( { fqn } ) ) {
216+ if ( pkg . name !== this . projectInfo . name && ! this . _dereference ( { fqn } , type . symbol . valueDeclaration ) ) {
210217 this . _diagnostic ( type . symbol . valueDeclaration ,
211218 ts . DiagnosticCategory . Error ,
212219 `Use of foreign type not present in the ${ pkg . name } 's assembly: ${ fqn } ` ) ;
@@ -314,7 +321,8 @@ export class Assembler implements Emitter {
314321 continue ;
315322 }
316323 this . _defer ( ( ) => {
317- if ( ! spec . isClassType ( this . _dereference ( ref ) ) ) {
324+ const deref = this . _dereference ( ref , base . symbol . valueDeclaration ) ;
325+ if ( deref && ! spec . isClassType ( deref ) ) {
318326 this . _diagnostic ( base . symbol . valueDeclaration ,
319327 ts . DiagnosticCategory . Error ,
320328 `Base type of ${ jsiiType . fqn } is not a class (${ spec . describeTypeReference ( ref ) } )` ) ;
@@ -340,7 +348,8 @@ export class Assembler implements Emitter {
340348 continue ;
341349 }
342350 this . _defer ( ( ) => {
343- if ( ! spec . isInterfaceType ( this . _dereference ( typeRef ) ) ) {
351+ const deref = this . _dereference ( typeRef , expression ) ;
352+ if ( deref && ! spec . isInterfaceType ( deref ) ) {
344353 this . _diagnostic ( expression ,
345354 ts . DiagnosticCategory . Error ,
346355 `Implements clause of ${ jsiiType . fqn } uses ${ spec . describeTypeReference ( typeRef ) } as an interface` ) ;
@@ -393,17 +402,15 @@ export class Assembler implements Emitter {
393402 }
394403 } else if ( jsiiType . base ) {
395404 this . _defer ( ( ) => {
396- const baseType = this . _dereference ( jsiiType . base ! ) ;
397- if ( ! baseType ) {
398- this . _diagnostic ( type . symbol . valueDeclaration ,
399- ts . DiagnosticCategory . Error ,
400- `Unable to resolve type ${ jsiiType . base ! . fqn } (base type of ${ jsiiType . fqn } )` ) ;
401- } else if ( spec . isClassType ( baseType ) ) {
402- jsiiType . initializer = baseType . initializer ;
403- } else {
404- this . _diagnostic ( type . symbol . valueDeclaration ,
405- ts . DiagnosticCategory . Error ,
406- `Base type of ${ jsiiType . fqn } (${ jsiiType . base ! . fqn } ) is not a class` ) ;
405+ const baseType = this . _dereference ( jsiiType . base ! , type . symbol . valueDeclaration ) ;
406+ if ( baseType ) {
407+ if ( spec . isClassType ( baseType ) ) {
408+ jsiiType . initializer = baseType . initializer ;
409+ } else {
410+ this . _diagnostic ( type . symbol . valueDeclaration ,
411+ ts . DiagnosticCategory . Error ,
412+ `Base type of ${ jsiiType . fqn } (${ jsiiType . base ! . fqn } ) is not a class` ) ;
413+ }
407414 }
408415 } ) ;
409416 } else {
@@ -499,17 +506,13 @@ export class Assembler implements Emitter {
499506 continue ;
500507 }
501508 this . _defer ( ( ) => {
502- if ( ! spec . isInterfaceType ( this . _dereference ( ref ) ) ) {
503- const baseType = this . _dereference ( ref ) ;
504- if ( baseType ) {
505- this . _diagnostic ( base . symbol . valueDeclaration ,
506- ts . DiagnosticCategory . Error ,
507- `Base type of ${ jsiiType . fqn } is not an interface (${ baseType . kind } ${ spec . describeTypeReference ( ref ) } )` ) ;
508- } else {
509- this . _diagnostic ( base . symbol . valueDeclaration ,
510- ts . DiagnosticCategory . Error ,
511- `Base type of ${ jsiiType . fqn } could not be resolved (${ spec . describeTypeReference ( ref ) } )` ) ;
512- }
509+ const baseType = this . _dereference ( ref , base . symbol . valueDeclaration ) ;
510+ if ( baseType && ! spec . isInterfaceType ( baseType ) ) {
511+ // tslint:disable:max-line-length
512+ this . _diagnostic ( base . symbol . valueDeclaration ,
513+ ts . DiagnosticCategory . Error ,
514+ `Base type of ${ jsiiType . fqn } is not an interface (${ baseType . kind } ${ spec . describeTypeReference ( ref ) } )` ) ;
515+ // tslint:enable:max-line-length
513516 }
514517 } ) ;
515518 if ( jsiiType . interfaces ) {
0 commit comments