diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d89247b70f978..8d8595409e83d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16381,6 +16381,12 @@ namespace ts { return resolveUntypedCall(node); } + if (isPotentiallyUncalledDecorator(node, callSignatures)) { + const nodeStr = getTextOfNode(node.expression, /*includeTrivia*/ false); + error(node, Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr); + return resolveErrorCall(node); + } + const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { let errorInfo: DiagnosticMessageChain; @@ -16393,6 +16399,18 @@ namespace ts { return resolveCall(node, callSignatures, candidatesOutArray, headMessage); } + /** + * Sometimes, we have a decorator that could accept zero arguments, + * but is receiving too many arguments as part of the decorator invocation. + * In those cases, a user may have meant to *call* the expression before using it as a decorator. + */ + 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)); + } + /** * This function is similar to getResolvedSignature but is exclusively for trying to resolve JSX stateless-function component. * The main reason we have to use this function instead of getResolvedSignature because, the caller of this function will already check the type of openingLikeElement's tagName diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index bf8fcdc4f84b3..eb508857e6f2e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -907,6 +907,10 @@ "category": "Error", "code": 1328 }, + "'{0}' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@{0}()'?": { + "category": "Error", + "code": 1329 + }, "Duplicate identifier '{0}'.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts old mode 100755 new mode 100644 diff --git a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt index 530e86117eeac..b863a9db72c9c 100644 --- a/tests/baselines/reference/decoratorOnClassMethod6.errors.txt +++ b/tests/baselines/reference/decoratorOnClassMethod6.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. +tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'? ==== tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/method/decoratorOnClassMethod6.ts(4,5): class C { @dec ["method"]() {} ~~~~ -!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'? } \ No newline at end of file diff --git a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt index 2a72fefa53ede..537daaf44ea6a 100644 --- a/tests/baselines/reference/decoratorOnClassProperty11.errors.txt +++ b/tests/baselines/reference/decoratorOnClassProperty11.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1240: Unable to resolve signature of property decorator when called as an expression. +tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts(4,5): error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'? ==== tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts (1 errors) ==== @@ -7,5 +7,5 @@ tests/cases/conformance/decorators/class/property/decoratorOnClassProperty11.ts( class C { @dec prop; ~~~~ -!!! error TS1240: Unable to resolve signature of property decorator when called as an expression. +!!! error TS1329: 'dec' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@dec()'? } \ No newline at end of file diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt b/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt new file mode 100644 index 0000000000000..9028ebe0377eb --- /dev/null +++ b/tests/baselines/reference/potentiallyUncalledDecorators.errors.txt @@ -0,0 +1,174 @@ +tests/cases/compiler/potentiallyUncalledDecorators.ts(4,5): error TS1329: 'Input' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@Input()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(35,1): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(37,5): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(38,5): error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(41,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof B'. + Type 'OmniDecorator' provides no match for the signature 'new (): B'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(43,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. + Unable to resolve signature of property decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(44,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. + Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(47,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof C'. + Type 'OmniDecorator' provides no match for the signature 'new (): C'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(49,5): error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(50,5): error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'? +tests/cases/compiler/potentiallyUncalledDecorators.ts(53,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof D'. + Type 'OmniDecorator' provides no match for the signature 'new (): D'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(55,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. + Unable to resolve signature of property decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(56,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. + Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(59,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof E'. + Type 'OmniDecorator' provides no match for the signature 'new (): E'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(61,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. + Unable to resolve signature of property decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(62,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. + Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(65,1): error TS1238: Unable to resolve signature of class decorator when called as an expression. + Type 'OmniDecorator' is not assignable to type 'typeof F'. + Type 'OmniDecorator' provides no match for the signature 'new (): F'. +tests/cases/compiler/potentiallyUncalledDecorators.ts(67,5): error TS1236: The return type of a property decorator function must be either 'void' or 'any'. + Unable to resolve signature of property decorator when called as an expression. +tests/cases/compiler/potentiallyUncalledDecorators.ts(68,5): error TS1241: Unable to resolve signature of method decorator when called as an expression. + Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + + +==== tests/cases/compiler/potentiallyUncalledDecorators.ts (19 errors) ==== + // Angular-style Input/Output API: + declare function Input(bindingPropertyName?: string): any; + class FooComponent { + @Input foo: string; + ~~~~~~ +!!! error TS1329: 'Input' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@Input()'? + } + + // 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; + declare const anyDec: any; + + @noArgs + ~~~~~~~ +!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? + class A { + @noArgs foo: any; + ~~~~~~~ +!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? + @noArgs bar() { } + ~~~~~~~ +!!! error TS1329: 'noArgs' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@noArgs()'? + } + + @allRest + ~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof B'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): B'. + class B { + @allRest foo: any; + ~~~~~~~~ +!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +!!! error TS1236: Unable to resolve signature of property decorator when called as an expression. + @allRest bar() { } + ~~~~~~~~ +!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + } + + @oneOptional + ~~~~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof C'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): C'. + class C { + @oneOptional foo: any; + ~~~~~~~~~~~~ +!!! error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'? + @oneOptional bar() { } + ~~~~~~~~~~~~ +!!! error TS1329: 'oneOptional' accepts too few arguments to be used as a decorator here. Did you mean to call it first and write '@oneOptional()'? + } + + @twoOptional + ~~~~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof D'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): D'. + class D { + @twoOptional foo: any; + ~~~~~~~~~~~~ +!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +!!! error TS1236: Unable to resolve signature of property decorator when called as an expression. + @twoOptional bar() { } + ~~~~~~~~~~~~ +!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + } + + @threeOptional + ~~~~~~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof E'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): E'. + class E { + @threeOptional foo: any; + ~~~~~~~~~~~~~~ +!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +!!! error TS1236: Unable to resolve signature of property decorator when called as an expression. + @threeOptional bar() { } + ~~~~~~~~~~~~~~ +!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + } + + @oneOptionalWithRest + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS1238: Unable to resolve signature of class decorator when called as an expression. +!!! error TS1238: Type 'OmniDecorator' is not assignable to type 'typeof F'. +!!! error TS1238: Type 'OmniDecorator' provides no match for the signature 'new (): F'. + class F { + @oneOptionalWithRest foo: any; + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS1236: The return type of a property decorator function must be either 'void' or 'any'. +!!! error TS1236: Unable to resolve signature of property decorator when called as an expression. + @oneOptionalWithRest bar() { } + ~~~~~~~~~~~~~~~~~~~~ +!!! error TS1241: Unable to resolve signature of method decorator when called as an expression. +!!! error TS1241: Type 'OmniDecorator' has no properties in common with type 'TypedPropertyDescriptor<() => void>'. + } + + @anyDec + class G { + @anyDec foo: any; + @anyDec bar() { } + } + + export { }; + \ No newline at end of file diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.js b/tests/baselines/reference/potentiallyUncalledDecorators.js new file mode 100644 index 0000000000000..b69f848a8c933 --- /dev/null +++ b/tests/baselines/reference/potentiallyUncalledDecorators.js @@ -0,0 +1,189 @@ +//// [potentiallyUncalledDecorators.ts] +// 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; +declare const anyDec: any; + +@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() { } +} + +@anyDec +class G { + @anyDec foo: any; + @anyDec bar() { } +} + +export { }; + + +//// [potentiallyUncalledDecorators.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +class FooComponent { +} +__decorate([ + Input +], FooComponent.prototype, "foo", void 0); +class Person { +} +__decorate([ + tracked +], Person.prototype, "person", void 0); +class MultiplyByTwo { + get multiplied() { + return this.args.number * 2; + } +} +__decorate([ + tracked('args') +], MultiplyByTwo.prototype, "multiplied", null); +let A = class A { + bar() { } +}; +__decorate([ + noArgs +], A.prototype, "foo", void 0); +__decorate([ + noArgs +], A.prototype, "bar", null); +A = __decorate([ + noArgs +], A); +let B = class B { + bar() { } +}; +__decorate([ + allRest +], B.prototype, "foo", void 0); +__decorate([ + allRest +], B.prototype, "bar", null); +B = __decorate([ + allRest +], B); +let C = class C { + bar() { } +}; +__decorate([ + oneOptional +], C.prototype, "foo", void 0); +__decorate([ + oneOptional +], C.prototype, "bar", null); +C = __decorate([ + oneOptional +], C); +let D = class D { + bar() { } +}; +__decorate([ + twoOptional +], D.prototype, "foo", void 0); +__decorate([ + twoOptional +], D.prototype, "bar", null); +D = __decorate([ + twoOptional +], D); +let E = class E { + bar() { } +}; +__decorate([ + threeOptional +], E.prototype, "foo", void 0); +__decorate([ + threeOptional +], E.prototype, "bar", null); +E = __decorate([ + threeOptional +], E); +let F = class F { + bar() { } +}; +__decorate([ + oneOptionalWithRest +], F.prototype, "foo", void 0); +__decorate([ + oneOptionalWithRest +], F.prototype, "bar", null); +F = __decorate([ + oneOptionalWithRest +], F); +let G = class G { + bar() { } +}; +__decorate([ + anyDec +], G.prototype, "foo", void 0); +__decorate([ + anyDec +], G.prototype, "bar", null); +G = __decorate([ + anyDec +], G); diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.symbols b/tests/baselines/reference/potentiallyUncalledDecorators.symbols new file mode 100644 index 0000000000000..38fe3f3dc520e --- /dev/null +++ b/tests/baselines/reference/potentiallyUncalledDecorators.symbols @@ -0,0 +1,200 @@ +=== tests/cases/compiler/potentiallyUncalledDecorators.ts === +// Angular-style Input/Output API: +declare function Input(bindingPropertyName?: string): any; +>Input : Symbol(Input, Decl(potentiallyUncalledDecorators.ts, 0, 0)) +>bindingPropertyName : Symbol(bindingPropertyName, Decl(potentiallyUncalledDecorators.ts, 1, 23)) + +class FooComponent { +>FooComponent : Symbol(FooComponent, Decl(potentiallyUncalledDecorators.ts, 1, 58)) + + @Input foo: string; +>Input : Symbol(Input, Decl(potentiallyUncalledDecorators.ts, 0, 0)) +>foo : Symbol(FooComponent.foo, Decl(potentiallyUncalledDecorators.ts, 2, 20)) +} + +// Glimmer-style tracked API: +declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; } +>tracked : Symbol(tracked, Decl(potentiallyUncalledDecorators.ts, 7, 13)) +>PropertyDecorator : Symbol(PropertyDecorator, Decl(lib.es5.d.ts, --, --)) +>watchedProperties : Symbol(watchedProperties, Decl(potentiallyUncalledDecorators.ts, 7, 46)) + +class Person { +>Person : Symbol(Person, Decl(potentiallyUncalledDecorators.ts, 7, 85)) + + @tracked person; any; +>tracked : Symbol(tracked, Decl(potentiallyUncalledDecorators.ts, 7, 13)) +>person : Symbol(Person.person, Decl(potentiallyUncalledDecorators.ts, 9, 14)) +>any : Symbol(Person.any, Decl(potentiallyUncalledDecorators.ts, 10, 20)) +} + +class MultiplyByTwo { +>MultiplyByTwo : Symbol(MultiplyByTwo, Decl(potentiallyUncalledDecorators.ts, 11, 1)) + + args: any; +>args : Symbol(MultiplyByTwo.args, Decl(potentiallyUncalledDecorators.ts, 13, 21)) + + @tracked('args') +>tracked : Symbol(tracked, Decl(potentiallyUncalledDecorators.ts, 7, 13)) + + get multiplied() { +>multiplied : Symbol(MultiplyByTwo.multiplied, Decl(potentiallyUncalledDecorators.ts, 14, 14)) + + return this.args.number * 2; +>this.args : Symbol(MultiplyByTwo.args, Decl(potentiallyUncalledDecorators.ts, 13, 21)) +>this : Symbol(MultiplyByTwo, Decl(potentiallyUncalledDecorators.ts, 11, 1)) +>args : Symbol(MultiplyByTwo.args, Decl(potentiallyUncalledDecorators.ts, 13, 21)) + } +} + +// Other fun stuff. + +interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator { +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) +>MethodDecorator : Symbol(MethodDecorator, Decl(lib.es5.d.ts, --, --)) +>ClassDecorator : Symbol(ClassDecorator, Decl(lib.es5.d.ts, --, --)) +>PropertyDecorator : Symbol(PropertyDecorator, Decl(lib.es5.d.ts, --, --)) +} + +declare function noArgs(): OmniDecorator; +>noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function allRest(...args: any[]): OmniDecorator; +>allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) +>args : Symbol(args, Decl(potentiallyUncalledDecorators.ts, 27, 25)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function oneOptional(x?: any): OmniDecorator; +>oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) +>x : Symbol(x, Decl(potentiallyUncalledDecorators.ts, 28, 29)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function twoOptional(x?: any, y?: any): OmniDecorator; +>twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) +>x : Symbol(x, Decl(potentiallyUncalledDecorators.ts, 29, 29)) +>y : Symbol(y, Decl(potentiallyUncalledDecorators.ts, 29, 37)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; +>threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) +>x : Symbol(x, Decl(potentiallyUncalledDecorators.ts, 30, 31)) +>y : Symbol(y, Decl(potentiallyUncalledDecorators.ts, 30, 39)) +>z : Symbol(z, Decl(potentiallyUncalledDecorators.ts, 30, 48)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; +>oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) +>x : Symbol(x, Decl(potentiallyUncalledDecorators.ts, 31, 37)) +>args : Symbol(args, Decl(potentiallyUncalledDecorators.ts, 31, 45)) +>OmniDecorator : Symbol(OmniDecorator, Decl(potentiallyUncalledDecorators.ts, 19, 1)) + +declare const anyDec: any; +>anyDec : Symbol(anyDec, Decl(potentiallyUncalledDecorators.ts, 32, 13)) + +@noArgs +>noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) + +class A { +>A : Symbol(A, Decl(potentiallyUncalledDecorators.ts, 32, 26)) + + @noArgs foo: any; +>noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) +>foo : Symbol(A.foo, Decl(potentiallyUncalledDecorators.ts, 35, 9)) + + @noArgs bar() { } +>noArgs : Symbol(noArgs, Decl(potentiallyUncalledDecorators.ts, 24, 1)) +>bar : Symbol(A.bar, Decl(potentiallyUncalledDecorators.ts, 36, 21)) +} + +@allRest +>allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) + +class B { +>B : Symbol(B, Decl(potentiallyUncalledDecorators.ts, 38, 1)) + + @allRest foo: any; +>allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) +>foo : Symbol(B.foo, Decl(potentiallyUncalledDecorators.ts, 41, 9)) + + @allRest bar() { } +>allRest : Symbol(allRest, Decl(potentiallyUncalledDecorators.ts, 26, 41)) +>bar : Symbol(B.bar, Decl(potentiallyUncalledDecorators.ts, 42, 22)) +} + +@oneOptional +>oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) + +class C { +>C : Symbol(C, Decl(potentiallyUncalledDecorators.ts, 44, 1)) + + @oneOptional foo: any; +>oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) +>foo : Symbol(C.foo, Decl(potentiallyUncalledDecorators.ts, 47, 9)) + + @oneOptional bar() { } +>oneOptional : Symbol(oneOptional, Decl(potentiallyUncalledDecorators.ts, 27, 56)) +>bar : Symbol(C.bar, Decl(potentiallyUncalledDecorators.ts, 48, 26)) +} + +@twoOptional +>twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) + +class D { +>D : Symbol(D, Decl(potentiallyUncalledDecorators.ts, 50, 1)) + + @twoOptional foo: any; +>twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) +>foo : Symbol(D.foo, Decl(potentiallyUncalledDecorators.ts, 53, 9)) + + @twoOptional bar() { } +>twoOptional : Symbol(twoOptional, Decl(potentiallyUncalledDecorators.ts, 28, 53)) +>bar : Symbol(D.bar, Decl(potentiallyUncalledDecorators.ts, 54, 26)) +} + +@threeOptional +>threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) + +class E { +>E : Symbol(E, Decl(potentiallyUncalledDecorators.ts, 56, 1)) + + @threeOptional foo: any; +>threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) +>foo : Symbol(E.foo, Decl(potentiallyUncalledDecorators.ts, 59, 9)) + + @threeOptional bar() { } +>threeOptional : Symbol(threeOptional, Decl(potentiallyUncalledDecorators.ts, 29, 62)) +>bar : Symbol(E.bar, Decl(potentiallyUncalledDecorators.ts, 60, 28)) +} + +@oneOptionalWithRest +>oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) + +class F { +>F : Symbol(F, Decl(potentiallyUncalledDecorators.ts, 62, 1)) + + @oneOptionalWithRest foo: any; +>oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) +>foo : Symbol(F.foo, Decl(potentiallyUncalledDecorators.ts, 65, 9)) + + @oneOptionalWithRest bar() { } +>oneOptionalWithRest : Symbol(oneOptionalWithRest, Decl(potentiallyUncalledDecorators.ts, 30, 73)) +>bar : Symbol(F.bar, Decl(potentiallyUncalledDecorators.ts, 66, 34)) +} + +@anyDec +>anyDec : Symbol(anyDec, Decl(potentiallyUncalledDecorators.ts, 32, 13)) + +class G { +>G : Symbol(G, Decl(potentiallyUncalledDecorators.ts, 68, 1)) + + @anyDec foo: any; +>anyDec : Symbol(anyDec, Decl(potentiallyUncalledDecorators.ts, 32, 13)) +>foo : Symbol(G.foo, Decl(potentiallyUncalledDecorators.ts, 71, 9)) + + @anyDec bar() { } +>anyDec : Symbol(anyDec, Decl(potentiallyUncalledDecorators.ts, 32, 13)) +>bar : Symbol(G.bar, Decl(potentiallyUncalledDecorators.ts, 72, 21)) +} + +export { }; + diff --git a/tests/baselines/reference/potentiallyUncalledDecorators.types b/tests/baselines/reference/potentiallyUncalledDecorators.types new file mode 100644 index 0000000000000..cad861fc7b417 --- /dev/null +++ b/tests/baselines/reference/potentiallyUncalledDecorators.types @@ -0,0 +1,206 @@ +=== tests/cases/compiler/potentiallyUncalledDecorators.ts === +// Angular-style Input/Output API: +declare function Input(bindingPropertyName?: string): any; +>Input : (bindingPropertyName?: string) => any +>bindingPropertyName : string + +class FooComponent { +>FooComponent : FooComponent + + @Input foo: string; +>Input : (bindingPropertyName?: string) => any +>foo : string +} + +// Glimmer-style tracked API: +declare const tracked: PropertyDecorator & { (...watchedProperties: string[]): any; } +>tracked : PropertyDecorator & ((...watchedProperties: string[]) => any) +>PropertyDecorator : PropertyDecorator +>watchedProperties : string[] + +class Person { +>Person : Person + + @tracked person; any; +>tracked : PropertyDecorator & ((...watchedProperties: string[]) => any) +>person : any +>any : any +} + +class MultiplyByTwo { +>MultiplyByTwo : MultiplyByTwo + + args: any; +>args : any + + @tracked('args') +>tracked('args') : any +>tracked : PropertyDecorator & ((...watchedProperties: string[]) => any) +>'args' : "args" + + get multiplied() { +>multiplied : number + + return this.args.number * 2; +>this.args.number * 2 : number +>this.args.number : any +>this.args : any +>this : this +>args : any +>number : any +>2 : 2 + } +} + +// Other fun stuff. + +interface OmniDecorator extends MethodDecorator, ClassDecorator, PropertyDecorator { +>OmniDecorator : OmniDecorator +>MethodDecorator : MethodDecorator +>ClassDecorator : ClassDecorator +>PropertyDecorator : PropertyDecorator +} + +declare function noArgs(): OmniDecorator; +>noArgs : () => OmniDecorator +>OmniDecorator : OmniDecorator + +declare function allRest(...args: any[]): OmniDecorator; +>allRest : (...args: any[]) => OmniDecorator +>args : any[] +>OmniDecorator : OmniDecorator + +declare function oneOptional(x?: any): OmniDecorator; +>oneOptional : (x?: any) => OmniDecorator +>x : any +>OmniDecorator : OmniDecorator + +declare function twoOptional(x?: any, y?: any): OmniDecorator; +>twoOptional : (x?: any, y?: any) => OmniDecorator +>x : any +>y : any +>OmniDecorator : OmniDecorator + +declare function threeOptional(x?: any, y?: any, z?: any): OmniDecorator; +>threeOptional : (x?: any, y?: any, z?: any) => OmniDecorator +>x : any +>y : any +>z : any +>OmniDecorator : OmniDecorator + +declare function oneOptionalWithRest(x?: any, ...args: any[]): OmniDecorator; +>oneOptionalWithRest : (x?: any, ...args: any[]) => OmniDecorator +>x : any +>args : any[] +>OmniDecorator : OmniDecorator + +declare const anyDec: any; +>anyDec : any + +@noArgs +>noArgs : () => OmniDecorator + +class A { +>A : A + + @noArgs foo: any; +>noArgs : () => OmniDecorator +>foo : any + + @noArgs bar() { } +>noArgs : () => OmniDecorator +>bar : () => void +} + +@allRest +>allRest : (...args: any[]) => OmniDecorator + +class B { +>B : B + + @allRest foo: any; +>allRest : (...args: any[]) => OmniDecorator +>foo : any + + @allRest bar() { } +>allRest : (...args: any[]) => OmniDecorator +>bar : () => void +} + +@oneOptional +>oneOptional : (x?: any) => OmniDecorator + +class C { +>C : C + + @oneOptional foo: any; +>oneOptional : (x?: any) => OmniDecorator +>foo : any + + @oneOptional bar() { } +>oneOptional : (x?: any) => OmniDecorator +>bar : () => void +} + +@twoOptional +>twoOptional : (x?: any, y?: any) => OmniDecorator + +class D { +>D : D + + @twoOptional foo: any; +>twoOptional : (x?: any, y?: any) => OmniDecorator +>foo : any + + @twoOptional bar() { } +>twoOptional : (x?: any, y?: any) => OmniDecorator +>bar : () => void +} + +@threeOptional +>threeOptional : (x?: any, y?: any, z?: any) => OmniDecorator + +class E { +>E : E + + @threeOptional foo: any; +>threeOptional : (x?: any, y?: any, z?: any) => OmniDecorator +>foo : any + + @threeOptional bar() { } +>threeOptional : (x?: any, y?: any, z?: any) => OmniDecorator +>bar : () => void +} + +@oneOptionalWithRest +>oneOptionalWithRest : (x?: any, ...args: any[]) => OmniDecorator + +class F { +>F : F + + @oneOptionalWithRest foo: any; +>oneOptionalWithRest : (x?: any, ...args: any[]) => OmniDecorator +>foo : any + + @oneOptionalWithRest bar() { } +>oneOptionalWithRest : (x?: any, ...args: any[]) => OmniDecorator +>bar : () => void +} + +@anyDec +>anyDec : any + +class G { +>G : G + + @anyDec foo: any; +>anyDec : any +>foo : any + + @anyDec bar() { } +>anyDec : any +>bar : () => void +} + +export { }; + diff --git a/tests/cases/compiler/potentiallyUncalledDecorators.ts b/tests/cases/compiler/potentiallyUncalledDecorators.ts new file mode 100644 index 0000000000000..6e537686d0f56 --- /dev/null +++ b/tests/cases/compiler/potentiallyUncalledDecorators.ts @@ -0,0 +1,81 @@ +// @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; +declare const anyDec: any; + +@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() { } +} + +@anyDec +class G { + @anyDec foo: any; + @anyDec bar() { } +} + +export { };