From 07bec2893f06004607494f22ada1dd2edefe771f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 19 Mar 2019 11:46:18 -0700 Subject: [PATCH] Adjust offset to account for 'this' parameter when emitting parameter decorators --- src/compiler/transformers/ts.ts | 9 ++++--- .../decoratorOnClassMethodParameter2.js | 26 +++++++++++++++++++ .../decoratorOnClassMethodParameter2.symbols | 18 +++++++++++++ .../decoratorOnClassMethodParameter2.types | 16 ++++++++++++ ...ratorOnClassMethodThisParameter.errors.txt | 14 ++++++++++ .../decoratorOnClassMethodThisParameter.js | 26 +++++++++++++++++++ ...ecoratorOnClassMethodThisParameter.symbols | 18 +++++++++++++ .../decoratorOnClassMethodThisParameter.types | 16 ++++++++++++ .../decoratorOnClassMethodParameter2.ts | 7 +++++ .../decoratorOnClassMethodThisParameter.ts | 7 +++++ 10 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/decoratorOnClassMethodParameter2.js create mode 100644 tests/baselines/reference/decoratorOnClassMethodParameter2.symbols create mode 100644 tests/baselines/reference/decoratorOnClassMethodParameter2.types create mode 100644 tests/baselines/reference/decoratorOnClassMethodThisParameter.errors.txt create mode 100644 tests/baselines/reference/decoratorOnClassMethodThisParameter.js create mode 100644 tests/baselines/reference/decoratorOnClassMethodThisParameter.symbols create mode 100644 tests/baselines/reference/decoratorOnClassMethodThisParameter.types create mode 100644 tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter2.ts create mode 100644 tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 4a127f3236dfd..63d621c665439 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1338,11 +1338,14 @@ namespace ts { let decorators: (ReadonlyArray | undefined)[] | undefined; if (node) { const parameters = node.parameters; - for (let i = 0; i < parameters.length; i++) { - const parameter = parameters[i]; + const firstParameterIsThis = parameters.length > 0 && parameterIsThisKeyword(parameters[0]); + const firstParameterOffset = firstParameterIsThis ? 1 : 0; + const numParameters = firstParameterIsThis ? parameters.length - 1 : parameters.length; + for (let i = 0; i < numParameters; i++) { + const parameter = parameters[i + firstParameterOffset]; if (decorators || parameter.decorators) { if (!decorators) { - decorators = new Array(parameters.length); + decorators = new Array(numParameters); } decorators[i] = parameter.decorators; diff --git a/tests/baselines/reference/decoratorOnClassMethodParameter2.js b/tests/baselines/reference/decoratorOnClassMethodParameter2.js new file mode 100644 index 0000000000000..1b52268117bfb --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodParameter2.js @@ -0,0 +1,26 @@ +//// [decoratorOnClassMethodParameter2.ts] +declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; + +class C { + method(this: C, @dec p: number) {} +} + +//// [decoratorOnClassMethodParameter2.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; +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var C = /** @class */ (function () { + function C() { + } + C.prototype.method = function (p) { }; + __decorate([ + __param(0, dec) + ], C.prototype, "method", null); + return C; +}()); diff --git a/tests/baselines/reference/decoratorOnClassMethodParameter2.symbols b/tests/baselines/reference/decoratorOnClassMethodParameter2.symbols new file mode 100644 index 0000000000000..efb8abc14335a --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodParameter2.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter2.ts === +declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; +>dec : Symbol(dec, Decl(decoratorOnClassMethodParameter2.ts, 0, 0)) +>target : Symbol(target, Decl(decoratorOnClassMethodParameter2.ts, 0, 21)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>propertyKey : Symbol(propertyKey, Decl(decoratorOnClassMethodParameter2.ts, 0, 36)) +>parameterIndex : Symbol(parameterIndex, Decl(decoratorOnClassMethodParameter2.ts, 0, 66)) + +class C { +>C : Symbol(C, Decl(decoratorOnClassMethodParameter2.ts, 0, 97)) + + method(this: C, @dec p: number) {} +>method : Symbol(C.method, Decl(decoratorOnClassMethodParameter2.ts, 2, 9)) +>this : Symbol(this, Decl(decoratorOnClassMethodParameter2.ts, 3, 11)) +>C : Symbol(C, Decl(decoratorOnClassMethodParameter2.ts, 0, 97)) +>dec : Symbol(dec, Decl(decoratorOnClassMethodParameter2.ts, 0, 0)) +>p : Symbol(p, Decl(decoratorOnClassMethodParameter2.ts, 3, 19)) +} diff --git a/tests/baselines/reference/decoratorOnClassMethodParameter2.types b/tests/baselines/reference/decoratorOnClassMethodParameter2.types new file mode 100644 index 0000000000000..12d9e2a022c12 --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodParameter2.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter2.ts === +declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; +>dec : (target: Object, propertyKey: string | symbol, parameterIndex: number) => void +>target : Object +>propertyKey : string | symbol +>parameterIndex : number + +class C { +>C : C + + method(this: C, @dec p: number) {} +>method : (this: C, p: number) => void +>this : C +>dec : (target: Object, propertyKey: string | symbol, parameterIndex: number) => void +>p : number +} diff --git a/tests/baselines/reference/decoratorOnClassMethodThisParameter.errors.txt b/tests/baselines/reference/decoratorOnClassMethodThisParameter.errors.txt new file mode 100644 index 0000000000000..f87a3fa7f39fb --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodThisParameter.errors.txt @@ -0,0 +1,14 @@ +tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts(4,17): error TS1003: Identifier expected. +tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts(4,17): error TS2680: A 'this' parameter must be the first parameter. + + +==== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts (2 errors) ==== + declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; + + class C { + method(@dec this: C) {} + ~~~~ +!!! error TS1003: Identifier expected. + ~~~~~~~ +!!! error TS2680: A 'this' parameter must be the first parameter. + } \ No newline at end of file diff --git a/tests/baselines/reference/decoratorOnClassMethodThisParameter.js b/tests/baselines/reference/decoratorOnClassMethodThisParameter.js new file mode 100644 index 0000000000000..74b835c1383e5 --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodThisParameter.js @@ -0,0 +1,26 @@ +//// [decoratorOnClassMethodThisParameter.ts] +declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; + +class C { + method(@dec this: C) {} +} + +//// [decoratorOnClassMethodThisParameter.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; +}; +var __param = (this && this.__param) || function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +}; +var C = /** @class */ (function () { + function C() { + } + C.prototype.method = function () { }; + __decorate([ + __param(0, dec) + ], C.prototype, "method", null); + return C; +}()); diff --git a/tests/baselines/reference/decoratorOnClassMethodThisParameter.symbols b/tests/baselines/reference/decoratorOnClassMethodThisParameter.symbols new file mode 100644 index 0000000000000..13d6bb152ee25 --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodThisParameter.symbols @@ -0,0 +1,18 @@ +=== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts === +declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; +>dec : Symbol(dec, Decl(decoratorOnClassMethodThisParameter.ts, 0, 0)) +>target : Symbol(target, Decl(decoratorOnClassMethodThisParameter.ts, 0, 21)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>propertyKey : Symbol(propertyKey, Decl(decoratorOnClassMethodThisParameter.ts, 0, 36)) +>parameterIndex : Symbol(parameterIndex, Decl(decoratorOnClassMethodThisParameter.ts, 0, 66)) + +class C { +>C : Symbol(C, Decl(decoratorOnClassMethodThisParameter.ts, 0, 97)) + + method(@dec this: C) {} +>method : Symbol(C.method, Decl(decoratorOnClassMethodThisParameter.ts, 2, 9)) +>dec : Symbol(dec, Decl(decoratorOnClassMethodThisParameter.ts, 0, 0)) +> : Symbol((Missing), Decl(decoratorOnClassMethodThisParameter.ts, 3, 11)) +>this : Symbol(this, Decl(decoratorOnClassMethodThisParameter.ts, 3, 15)) +>C : Symbol(C, Decl(decoratorOnClassMethodThisParameter.ts, 0, 97)) +} diff --git a/tests/baselines/reference/decoratorOnClassMethodThisParameter.types b/tests/baselines/reference/decoratorOnClassMethodThisParameter.types new file mode 100644 index 0000000000000..8b58cb7b49390 --- /dev/null +++ b/tests/baselines/reference/decoratorOnClassMethodThisParameter.types @@ -0,0 +1,16 @@ +=== tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts === +declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; +>dec : (target: Object, propertyKey: string | symbol, parameterIndex: number) => void +>target : Object +>propertyKey : string | symbol +>parameterIndex : number + +class C { +>C : C + + method(@dec this: C) {} +>method : (: any, this: C) => void +>dec : (target: Object, propertyKey: string | symbol, parameterIndex: number) => void +> : any +>this : C +} diff --git a/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter2.ts b/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter2.ts new file mode 100644 index 0000000000000..1a8c6faf84b10 --- /dev/null +++ b/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodParameter2.ts @@ -0,0 +1,7 @@ +// @target:es5 +// @experimentaldecorators: true +declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; + +class C { + method(this: C, @dec p: number) {} +} \ No newline at end of file diff --git a/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts b/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts new file mode 100644 index 0000000000000..d111fc9047ac1 --- /dev/null +++ b/tests/cases/conformance/decorators/class/method/parameter/decoratorOnClassMethodThisParameter.ts @@ -0,0 +1,7 @@ +// @target:es5 +// @experimentaldecorators: true +declare function dec(target: Object, propertyKey: string | symbol, parameterIndex: number): void; + +class C { + method(@dec this: C) {} +} \ No newline at end of file