@@ -191,7 +191,7 @@ export function extractDirectiveMetadata(
191
191
if ( ! ts . isObjectLiteralExpression ( meta ) ) {
192
192
throw new FatalDiagnosticError (
193
193
ErrorCode . DECORATOR_ARG_NOT_LITERAL , meta ,
194
- `@${ decorator . name } argument must be literal. ` ) ;
194
+ `@${ decorator . name } argument must be an object literal` ) ;
195
195
}
196
196
directive = reflectObjectLiteral ( meta ) ;
197
197
}
@@ -345,7 +345,7 @@ export function extractQueryMetadata(
345
345
predicate = new WrappedNodeExpr ( node ) ;
346
346
} else if ( typeof arg === 'string' ) {
347
347
predicate = [ arg ] ;
348
- } else if ( isStringArrayOrDie ( arg , '@' + name ) ) {
348
+ } else if ( isStringArrayOrDie ( arg , `@ ${ name } predicate` , node ) ) {
349
349
predicate = arg ;
350
350
} else {
351
351
throw new FatalDiagnosticError (
@@ -359,17 +359,22 @@ export function extractQueryMetadata(
359
359
if ( args . length === 2 ) {
360
360
const optionsExpr = unwrapExpression ( args [ 1 ] ) ;
361
361
if ( ! ts . isObjectLiteralExpression ( optionsExpr ) ) {
362
- throw new Error ( `@${ name } options must be an object literal` ) ;
362
+ throw new FatalDiagnosticError (
363
+ ErrorCode . DECORATOR_ARG_NOT_LITERAL , optionsExpr ,
364
+ `@${ name } options must be an object literal` ) ;
363
365
}
364
366
const options = reflectObjectLiteral ( optionsExpr ) ;
365
367
if ( options . has ( 'read' ) ) {
366
368
read = new WrappedNodeExpr ( options . get ( 'read' ) ! ) ;
367
369
}
368
370
369
371
if ( options . has ( 'descendants' ) ) {
370
- const descendantsValue = evaluator . evaluate ( options . get ( 'descendants' ) ! ) ;
372
+ const descendantsExpr = options . get ( 'descendants' ) ! ;
373
+ const descendantsValue = evaluator . evaluate ( descendantsExpr ) ;
371
374
if ( typeof descendantsValue !== 'boolean' ) {
372
- throw new Error ( `@${ name } options.descendants must be a boolean` ) ;
375
+ throw new FatalDiagnosticError (
376
+ ErrorCode . VALUE_HAS_WRONG_TYPE , descendantsExpr ,
377
+ `@${ name } options.descendants must be a boolean` ) ;
373
378
}
374
379
descendants = descendantsValue ;
375
380
}
@@ -385,7 +390,8 @@ export function extractQueryMetadata(
385
390
386
391
} else if ( args . length > 2 ) {
387
392
// Too many arguments.
388
- throw new Error ( `@${ name } has too many arguments` ) ;
393
+ throw new FatalDiagnosticError (
394
+ ErrorCode . DECORATOR_ARITY_WRONG , node , `@${ name } has too many arguments` ) ;
389
395
}
390
396
391
397
return {
@@ -406,17 +412,23 @@ export function extractQueriesFromDecorator(
406
412
} {
407
413
const content : R3QueryMetadata [ ] = [ ] , view : R3QueryMetadata [ ] = [ ] ;
408
414
if ( ! ts . isObjectLiteralExpression ( queryData ) ) {
409
- throw new Error ( `queries metadata must be an object literal` ) ;
415
+ throw new FatalDiagnosticError (
416
+ ErrorCode . VALUE_HAS_WRONG_TYPE , queryData ,
417
+ 'Decorator queries metadata must be an object literal' ) ;
410
418
}
411
419
reflectObjectLiteral ( queryData ) . forEach ( ( queryExpr , propertyName ) => {
412
420
queryExpr = unwrapExpression ( queryExpr ) ;
413
421
if ( ! ts . isNewExpression ( queryExpr ) || ! ts . isIdentifier ( queryExpr . expression ) ) {
414
- throw new Error ( `query metadata must be an instance of a query type` ) ;
422
+ throw new FatalDiagnosticError (
423
+ ErrorCode . VALUE_HAS_WRONG_TYPE , queryData ,
424
+ 'Decorator query metadata must be an instance of a query type' ) ;
415
425
}
416
426
const type = reflector . getImportOfIdentifier ( queryExpr . expression ) ;
417
427
if ( type === null || ( ! isCore && type . from !== '@angular/core' ) ||
418
428
! QUERY_TYPES . has ( type . name ) ) {
419
- throw new Error ( `query metadata must be an instance of a query type` ) ;
429
+ throw new FatalDiagnosticError (
430
+ ErrorCode . VALUE_HAS_WRONG_TYPE , queryData ,
431
+ 'Decorator query metadata must be an instance of a query type' ) ;
420
432
}
421
433
422
434
const query = extractQueryMetadata (
@@ -430,14 +442,16 @@ export function extractQueriesFromDecorator(
430
442
return { content, view} ;
431
443
}
432
444
433
- function isStringArrayOrDie ( value : any , name : string ) : value is string [ ] {
445
+ function isStringArrayOrDie ( value : any , name : string , node : ts . Expression ) : value is string [ ] {
434
446
if ( ! Array . isArray ( value ) ) {
435
447
return false ;
436
448
}
437
449
438
450
for ( let i = 0 ; i < value . length ; i ++ ) {
439
451
if ( typeof value [ i ] !== 'string' ) {
440
- throw new Error ( `Failed to resolve ${ name } [${ i } ] to a string` ) ;
452
+ throw new FatalDiagnosticError (
453
+ ErrorCode . VALUE_HAS_WRONG_TYPE , node ,
454
+ `Failed to resolve ${ name } at position ${ i } to a string` ) ;
441
455
}
442
456
}
443
457
return true ;
@@ -451,9 +465,12 @@ export function parseFieldArrayValue(
451
465
}
452
466
453
467
// Resolve the field of interest from the directive metadata to a string[].
454
- const value = evaluator . evaluate ( directive . get ( field ) ! ) ;
455
- if ( ! isStringArrayOrDie ( value , field ) ) {
456
- throw new Error ( `Failed to resolve @Directive.${ field } ` ) ;
468
+ const expression = directive . get ( field ) ! ;
469
+ const value = evaluator . evaluate ( expression ) ;
470
+ if ( ! isStringArrayOrDie ( value , field , expression ) ) {
471
+ throw new FatalDiagnosticError (
472
+ ErrorCode . VALUE_HAS_WRONG_TYPE , expression ,
473
+ `Failed to resolve @Directive.${ field } to a string array` ) ;
457
474
}
458
475
459
476
return value ;
@@ -501,13 +518,16 @@ function parseDecoratedFields(
501
518
} else if ( decorator . args . length === 1 ) {
502
519
const property = evaluator . evaluate ( decorator . args [ 0 ] ) ;
503
520
if ( typeof property !== 'string' ) {
504
- throw new Error ( `Decorator argument must resolve to a string` ) ;
521
+ throw new FatalDiagnosticError (
522
+ ErrorCode . VALUE_HAS_WRONG_TYPE , Decorator . nodeForError ( decorator ) ,
523
+ `@${ decorator . name } decorator argument must resolve to a string` ) ;
505
524
}
506
525
results [ fieldName ] = mapValueResolver ( property , fieldName ) ;
507
526
} else {
508
527
// Too many arguments.
509
- throw new Error (
510
- `Decorator must have 0 or 1 arguments, got ${ decorator . args . length } argument(s)` ) ;
528
+ throw new FatalDiagnosticError (
529
+ ErrorCode . DECORATOR_ARITY_WRONG , Decorator . nodeForError ( decorator ) ,
530
+ `@${ decorator . name } can have at most one argument, got ${ decorator . args . length } argument(s)` ) ;
511
531
}
512
532
} ) ;
513
533
return results ;
@@ -568,7 +588,7 @@ export function extractHostBindings(
568
588
const hostMetaMap = evaluator . evaluate ( expr ) ;
569
589
if ( ! ( hostMetaMap instanceof Map ) ) {
570
590
throw new FatalDiagnosticError (
571
- ErrorCode . DECORATOR_ARG_NOT_LITERAL , expr , `Decorator host metadata must be an object` ) ;
591
+ ErrorCode . VALUE_HAS_WRONG_TYPE , expr , `Decorator host metadata must be an object` ) ;
572
592
}
573
593
hostMetaMap . forEach ( ( value , key ) => {
574
594
// Resolve Enum references to their declared value.
@@ -577,17 +597,19 @@ export function extractHostBindings(
577
597
}
578
598
579
599
if ( typeof key !== 'string' ) {
580
- throw new Error (
581
- `Decorator host metadata must be a string -> string object, but found unparseable key ${ key } ` ) ;
600
+ throw new FatalDiagnosticError (
601
+ ErrorCode . VALUE_HAS_WRONG_TYPE , expr ,
602
+ `Decorator host metadata must be a string -> string object, but found unparseable key` ) ;
582
603
}
583
604
584
605
if ( typeof value == 'string' ) {
585
606
hostMetadata [ key ] = value ;
586
607
} else if ( value instanceof DynamicValue ) {
587
608
hostMetadata [ key ] = new WrappedNodeExpr ( value . node as ts . Expression ) ;
588
609
} else {
589
- throw new Error (
590
- `Decorator host metadata must be a string -> string object, but found unparseable value ${ value } ` ) ;
610
+ throw new FatalDiagnosticError (
611
+ ErrorCode . VALUE_HAS_WRONG_TYPE , expr ,
612
+ `Decorator host metadata must be a string -> string object, but found unparseable value` ) ;
591
613
}
592
614
} ) ;
593
615
}
@@ -605,26 +627,29 @@ export function extractHostBindings(
605
627
errors . map ( ( error : ParseError ) => error . msg ) . join ( '\n' ) ) ;
606
628
}
607
629
608
- filterToMembersWithDecorator ( members , 'HostBinding' , coreModule )
609
- . forEach ( ( { member, decorators} ) => {
610
- decorators . forEach ( decorator => {
611
- let hostPropertyName : string = member . name ;
612
- if ( decorator . args !== null && decorator . args . length > 0 ) {
613
- if ( decorator . args . length !== 1 ) {
614
- throw new Error ( `@HostBinding() can have at most one argument` ) ;
615
- }
630
+ filterToMembersWithDecorator ( members , 'HostBinding' , coreModule ) . forEach ( ( { member, decorators} ) => {
631
+ decorators . forEach ( decorator => {
632
+ let hostPropertyName : string = member . name ;
633
+ if ( decorator . args !== null && decorator . args . length > 0 ) {
634
+ if ( decorator . args . length !== 1 ) {
635
+ throw new FatalDiagnosticError (
636
+ ErrorCode . DECORATOR_ARITY_WRONG , Decorator . nodeForError ( decorator ) ,
637
+ `@HostBinding can have at most one argument, got ${ decorator . args . length } argument(s)` ) ;
638
+ }
616
639
617
- const resolved = evaluator . evaluate ( decorator . args [ 0 ] ) ;
618
- if ( typeof resolved !== 'string' ) {
619
- throw new Error ( `@HostBinding()'s argument must be a string` ) ;
620
- }
640
+ const resolved = evaluator . evaluate ( decorator . args [ 0 ] ) ;
641
+ if ( typeof resolved !== 'string' ) {
642
+ throw new FatalDiagnosticError (
643
+ ErrorCode . VALUE_HAS_WRONG_TYPE , Decorator . nodeForError ( decorator ) ,
644
+ `@HostBinding's argument must be a string` ) ;
645
+ }
621
646
622
- hostPropertyName = resolved ;
623
- }
647
+ hostPropertyName = resolved ;
648
+ }
624
649
625
- bindings . properties [ hostPropertyName ] = member . name ;
626
- } ) ;
627
- } ) ;
650
+ bindings . properties [ hostPropertyName ] = member . name ;
651
+ } ) ;
652
+ } ) ;
628
653
629
654
filterToMembersWithDecorator ( members , 'HostListener' , coreModule )
630
655
. forEach ( ( { member, decorators} ) => {
@@ -635,24 +660,25 @@ export function extractHostBindings(
635
660
if ( decorator . args . length > 2 ) {
636
661
throw new FatalDiagnosticError (
637
662
ErrorCode . DECORATOR_ARITY_WRONG , decorator . args [ 2 ] ,
638
- `@HostListener() can have at most two arguments` ) ;
663
+ `@HostListener can have at most two arguments` ) ;
639
664
}
640
665
641
666
const resolved = evaluator . evaluate ( decorator . args [ 0 ] ) ;
642
667
if ( typeof resolved !== 'string' ) {
643
668
throw new FatalDiagnosticError (
644
669
ErrorCode . VALUE_HAS_WRONG_TYPE , decorator . args [ 0 ] ,
645
- `@HostListener() 's event name argument must be a string` ) ;
670
+ `@HostListener's event name argument must be a string` ) ;
646
671
}
647
672
648
673
eventName = resolved ;
649
674
650
675
if ( decorator . args . length === 2 ) {
676
+ const expression = decorator . args [ 1 ] ;
651
677
const resolvedArgs = evaluator . evaluate ( decorator . args [ 1 ] ) ;
652
- if ( ! isStringArrayOrDie ( resolvedArgs , '@HostListener.args' ) ) {
678
+ if ( ! isStringArrayOrDie ( resolvedArgs , '@HostListener.args' , expression ) ) {
653
679
throw new FatalDiagnosticError (
654
680
ErrorCode . VALUE_HAS_WRONG_TYPE , decorator . args [ 1 ] ,
655
- `@HostListener second argument must be a string array` ) ;
681
+ `@HostListener's second argument must be a string array` ) ;
656
682
}
657
683
args = resolvedArgs ;
658
684
}
0 commit comments