From 86315ed4119db22cc900b58d053f471d4d354119 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 29 Sep 2017 22:01:00 -0700 Subject: [PATCH] Added test and adjusted reporting logic. --- src/compiler/checker.ts | 3 +- src/compiler/diagnosticMessages.json | 2 +- src/compiler/emitter.ts | 0 .../compiler/potentiallyUncalledDecorators.ts | 74 +++++++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) mode change 100755 => 100644 src/compiler/emitter.ts create mode 100644 tests/cases/compiler/potentiallyUncalledDecorators.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a272ac15e72..23da94437ae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16382,7 +16382,7 @@ namespace ts { } if (isPotentiallyUncalledDecorator(node, callSignatures)) { - error(node, Diagnostics.This_function_cannot_be_used_as_a_decorator_Did_you_mean_to_call_it_first); + error(node, Diagnostics.This_value_has_type_0_which_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first, typeToString(funcType)); return resolveErrorCall(node); } @@ -16406,6 +16406,7 @@ namespace ts { function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: Signature[]) { return signatures.length && every(signatures, signature => signature.minArgumentCount === 0 && + !signature.hasRestParameter && signature.parameters.length < getEffectiveArgumentCount(decorator, /*args*/ undefined, signature)); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 722985aac78..57dc9f28834 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -907,7 +907,7 @@ "category": "Error", "code": 1328 }, - "This function cannot be used as a decorator. Did you mean to call it first?": { + "This value has type '{0}' which accepts too few arguments to be used as a decorator here. Did you mean to call it first?": { "category": "Error", "code": 1329 }, diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts old mode 100755 new mode 100644 diff --git a/tests/cases/compiler/potentiallyUncalledDecorators.ts b/tests/cases/compiler/potentiallyUncalledDecorators.ts new file mode 100644 index 00000000000..3c92a21eff0 --- /dev/null +++ b/tests/cases/compiler/potentiallyUncalledDecorators.ts @@ -0,0 +1,74 @@ +// @target: esnext +// @module: esnext +// @experimentalDecorators: true + +// Angular-style Input/Output API: +declare function Input(bindingPropertyName?: string): any; +class FooComponent { + @Input foo: string; +} + +// Glimmer-style tracked API: +declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; } + +class Person { + @tracked person; any; +} + +class MultiplyByTwo { + args: any; + @tracked('args') + get multiplied() { + return this.args.number * 2; + } +} + +// Other fun stuff. + +interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator { +} + +declare function noArgs(): OmniDecorator; +declare function allRest(...args: any[]): OmniDecorator; +declare function oneOptional(x?: any): OmniDecorator; +declare function twoOptional(x?: any, y?: any): OmniDecorator; +declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; +declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; + +@noArgs +class A { + @noArgs foo: any; + @noArgs bar() { } +} + +@allRest +class B { + @allRest foo: any; + @allRest bar() { } +} + +@oneOptional +class C { + @oneOptional foo: any; + @oneOptional bar() { } +} + +@twoOptional +class D { + @twoOptional foo: any; + @twoOptional bar() { } +} + +@threeOptional +class E { + @threeOptional foo: any; + @threeOptional bar() { } +} + +@oneOptionalWithRest +class F { + @oneOptionalWithRest foo: any; + @oneOptionalWithRest bar() { } +} + +export { };