Adjust offset to account for 'this' parameter when emitting parameter decorators

This commit is contained in:
Ron Buckton 2019-03-19 11:46:18 -07:00
parent 4b3178cf77
commit 07bec2893f
10 changed files with 154 additions and 3 deletions

View File

@ -1338,11 +1338,14 @@ namespace ts {
let decorators: (ReadonlyArray<Decorator> | 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;

View File

@ -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;
}());

View File

@ -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))
}

View File

@ -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
}

View File

@ -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.
}

View File

@ -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;
}());

View File

@ -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))
}

View File

@ -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
}

View File

@ -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) {}
}

View File

@ -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) {}
}