diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f175b6806551b..8d060bae71b75 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2838,7 +2838,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else if (isClassLike(declaration)) { // still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} }) - return !findAncestor(usage, n => isComputedPropertyName(n) && n.parent.parent === declaration); + // or when used within a decorator in the class (e.g. `@dec(A.x) class A { static x = "x" }`), + // except when used in a function that is not an IIFE (e.g., `@dec(() => A.x) class A { ... }`) + const container = findAncestor(usage, n => + n === declaration ? "quit" : + isComputedPropertyName(n) ? n.parent.parent === declaration : + isDecorator(n) && (n.parent === declaration || + isMethodDeclaration(n.parent) && n.parent.parent === declaration || + isGetOrSetAccessorDeclaration(n.parent) && n.parent.parent === declaration || + isPropertyDeclaration(n.parent) && n.parent.parent === declaration || + isParameter(n.parent) && n.parent.parent.parent === declaration)); + if (!container) { + return true; + } + if (isDecorator(container)) { + return !!findAncestor(usage, n => n === container ? "quit" : isFunctionLike(n) && !getImmediatelyInvokedFunctionExpression(n)); + } + return false; } else if (isPropertyDeclaration(declaration)) { // still might be illegal if a self-referencing property initializer (eg private x = this.x) diff --git a/tests/baselines/reference/decoratorReferences.js b/tests/baselines/reference/decoratorReferences.js index dbf57c8a8f8a7..124a469f2986f 100644 --- a/tests/baselines/reference/decoratorReferences.js +++ b/tests/baselines/reference/decoratorReferences.js @@ -3,7 +3,7 @@ //// [decoratorReferences.ts] declare function y(...args: any[]): any; type T = number; -@y(1 as T, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class +@y(1 as T, () => C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class class C { @y(null as T) // <-- y should resolve to the function declaration, not the parameter; T should resolve to the type parameter of the class method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter. @@ -29,7 +29,7 @@ var C = /** @class */ (function () { __param(0, y) ], C.prototype, "method", null); C = __decorate([ - y(1, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class + y(1, function () { return C; }) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class ], C); return C; }()); diff --git a/tests/baselines/reference/decoratorReferences.symbols b/tests/baselines/reference/decoratorReferences.symbols index 96ef42ed96958..f5b4cc20364fa 100644 --- a/tests/baselines/reference/decoratorReferences.symbols +++ b/tests/baselines/reference/decoratorReferences.symbols @@ -8,7 +8,7 @@ declare function y(...args: any[]): any; type T = number; >T : Symbol(T, Decl(decoratorReferences.ts, 0, 40)) -@y(1 as T, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class +@y(1 as T, () => C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class >y : Symbol(y, Decl(decoratorReferences.ts, 0, 0)) >T : Symbol(T, Decl(decoratorReferences.ts, 0, 40)) >C : Symbol(C, Decl(decoratorReferences.ts, 1, 16)) diff --git a/tests/baselines/reference/decoratorReferences.types b/tests/baselines/reference/decoratorReferences.types index c5818a72535bd..c0ab3b286de15 100644 --- a/tests/baselines/reference/decoratorReferences.types +++ b/tests/baselines/reference/decoratorReferences.types @@ -8,11 +8,12 @@ declare function y(...args: any[]): any; type T = number; >T : number -@y(1 as T, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class ->y(1 as T, C) : any +@y(1 as T, () => C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class +>y(1 as T, () => C) : any >y : (...args: any[]) => any >1 as T : number >1 : 1 +>() => C : () => typeof C >C : typeof C class C { diff --git a/tests/baselines/reference/useBeforeDeclaration_classDecorators.1.errors.txt b/tests/baselines/reference/useBeforeDeclaration_classDecorators.1.errors.txt new file mode 100644 index 0000000000000..ec820f5b8a1c4 --- /dev/null +++ b/tests/baselines/reference/useBeforeDeclaration_classDecorators.1.errors.txt @@ -0,0 +1,147 @@ +useBeforeDeclaration_classDecorators.1.ts(7,6): error TS2449: Class 'C2' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(10,13): error TS2449: Class 'C3' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(29,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(30,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(31,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(32,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(33,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(35,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(36,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(37,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(38,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(39,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(44,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(45,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(46,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(47,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(48,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(50,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(51,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(52,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(53,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.1.ts(54,17): error TS2449: Class 'C6' used before its declaration. + + +==== useBeforeDeclaration_classDecorators.1.ts (22 errors) ==== + declare const dec: any; + + // ok + @dec(() => C1) class C1 { } + + // error + @dec(C2) class C2 { } + ~~ +!!! error TS2449: Class 'C2' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:7:16: 'C2' is declared here. + + // error + @dec((() => C3)()) class C3 { } + ~~ +!!! error TS2449: Class 'C3' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:10:26: 'C3' is declared here. + + // ok + class C4 { + @dec(() => C4) static method() {} + @dec(() => C4) static get x() { return this.y; } + @dec(() => C4) static set x(v) {} + @dec(() => C4) static y: any; + @dec(() => C4) static accessor z: any; + + @dec(() => C4) method() {} + @dec(() => C4) get x() { return this.y; } + @dec(() => C4) set x(v) {} + @dec(() => C4) y: any; + @dec(() => C4) accessor z: any; + } + + // error + class C5 { + @dec(C5) static method() {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + @dec(C5) static get x() { return this.y; } + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + @dec(C5) static set x(v) {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + @dec(C5) static y: any; + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + @dec(C5) static accessor z: any; + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + + @dec(C5) method() {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + @dec(C5) get x() { return this.y; } + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + @dec(C5) set x(v) {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + @dec(C5) y: any; + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + @dec(C5) accessor z: any; + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:28:7: 'C5' is declared here. + } + + // error + class C6 { + @dec((() => C6)()) static method() {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + @dec((() => C6)()) static get x() { return this.y; } + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + @dec((() => C6)()) static set x(v) {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + @dec((() => C6)()) static y: any; + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + @dec((() => C6)()) static accessor z: any; + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + + @dec((() => C6)()) method() {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + @dec((() => C6)()) get x() { return this.y; } + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + @dec((() => C6)()) set x(v) {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + @dec((() => C6)()) y: any; + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + @dec((() => C6)()) accessor z: any; + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.1.ts:43:7: 'C6' is declared here. + } + \ No newline at end of file diff --git a/tests/baselines/reference/useBeforeDeclaration_classDecorators.2.errors.txt b/tests/baselines/reference/useBeforeDeclaration_classDecorators.2.errors.txt new file mode 100644 index 0000000000000..567b26d168527 --- /dev/null +++ b/tests/baselines/reference/useBeforeDeclaration_classDecorators.2.errors.txt @@ -0,0 +1,203 @@ +useBeforeDeclaration_classDecorators.2.ts(7,6): error TS2449: Class 'C2' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(10,13): error TS2449: Class 'C3' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(16,5): error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. +useBeforeDeclaration_classDecorators.2.ts(22,5): error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. +useBeforeDeclaration_classDecorators.2.ts(33,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(34,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(35,5): error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. +useBeforeDeclaration_classDecorators.2.ts(35,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(36,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(37,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(39,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(40,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(41,5): error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. +useBeforeDeclaration_classDecorators.2.ts(41,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(42,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(43,10): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(46,22): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(47,25): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(48,18): error TS2449: Class 'C5' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(53,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(54,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(55,5): error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. +useBeforeDeclaration_classDecorators.2.ts(55,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(56,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(57,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(59,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(60,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(61,5): error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. +useBeforeDeclaration_classDecorators.2.ts(61,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(62,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(63,17): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(66,29): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(67,32): error TS2449: Class 'C6' used before its declaration. +useBeforeDeclaration_classDecorators.2.ts(68,25): error TS2449: Class 'C6' used before its declaration. + + +==== useBeforeDeclaration_classDecorators.2.ts (34 errors) ==== + declare const dec: any; + + // ok + @dec(() => C1) class C1 { } + + // error + @dec(C2) class C2 { } + ~~ +!!! error TS2449: Class 'C2' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:7:16: 'C2' is declared here. + + // error + @dec((() => C3)()) class C3 { } + ~~ +!!! error TS2449: Class 'C3' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:10:26: 'C3' is declared here. + + // ok + class C4 { + @dec(() => C4) static method() {} + @dec(() => C4) static get x() { return this.y; } + @dec(() => C4) static set x(v) {} + ~ +!!! error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. + @dec(() => C4) static y: any; + @dec(() => C4) static accessor z: any; + + @dec(() => C4) method() {} + @dec(() => C4) get x() { return this.y; } + @dec(() => C4) set x(v) {} + ~ +!!! error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. + @dec(() => C4) y: any; + @dec(() => C4) accessor z: any; + + constructor(@dec(() => C4) a: any) {} + static method2(@dec(() => C4) a: any) {} + method2(@dec(() => C4) a: any) {} + } + + // error + class C5 { + @dec(C5) static method() {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + @dec(C5) static get x() { return this.y; } + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + @dec(C5) static set x(v) {} + ~ +!!! error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + @dec(C5) static y: any; + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + @dec(C5) static accessor z: any; + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + + @dec(C5) method() {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + @dec(C5) get x() { return this.y; } + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + @dec(C5) set x(v) {} + ~ +!!! error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + @dec(C5) y: any; + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + @dec(C5) accessor z: any; + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + + + constructor(@dec(C5) a: any) {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + static method2(@dec(C5) a: any) {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + method2(@dec(C5) a: any) {} + ~~ +!!! error TS2449: Class 'C5' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:32:7: 'C5' is declared here. + } + + // error + class C6 { + @dec((() => C6)()) static method() {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + @dec((() => C6)()) static get x() { return this.y; } + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + @dec((() => C6)()) static set x(v) {} + ~ +!!! error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + @dec((() => C6)()) static y: any; + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + @dec((() => C6)()) static accessor z: any; + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + + @dec((() => C6)()) method() {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + @dec((() => C6)()) get x() { return this.y; } + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + @dec((() => C6)()) set x(v) {} + ~ +!!! error TS1207: Decorators cannot be applied to multiple get/set accessors of the same name. + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + @dec((() => C6)()) y: any; + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + @dec((() => C6)()) accessor z: any; + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + + + constructor(@dec((() => C6)()) a: any) {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + static method2(@dec((() => C6)()) a: any) {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + method2(@dec((() => C6)()) a: any) {} + ~~ +!!! error TS2449: Class 'C6' used before its declaration. +!!! related TS2728 useBeforeDeclaration_classDecorators.2.ts:52:7: 'C6' is declared here. + } + \ No newline at end of file diff --git a/tests/cases/compiler/decoratorReferences.ts b/tests/cases/compiler/decoratorReferences.ts index c6222e67fd929..faa257983d20f 100644 --- a/tests/cases/compiler/decoratorReferences.ts +++ b/tests/cases/compiler/decoratorReferences.ts @@ -2,7 +2,7 @@ declare function y(...args: any[]): any; type T = number; -@y(1 as T, C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class +@y(1 as T, () => C) // <-- T should be resolved to the type alias, not the type parameter of the class; C should resolve to the class class C { @y(null as T) // <-- y should resolve to the function declaration, not the parameter; T should resolve to the type parameter of the class method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter. diff --git a/tests/cases/compiler/useBeforeDeclaration_classDecorators.1.ts b/tests/cases/compiler/useBeforeDeclaration_classDecorators.1.ts new file mode 100644 index 0000000000000..25c55dd0bcf51 --- /dev/null +++ b/tests/cases/compiler/useBeforeDeclaration_classDecorators.1.ts @@ -0,0 +1,59 @@ +// @target: esnext +// @noEmit: true +// @noTypesAndSymbols: true + +declare const dec: any; + +// ok +@dec(() => C1) class C1 { } + +// error +@dec(C2) class C2 { } + +// error +@dec((() => C3)()) class C3 { } + +// ok +class C4 { + @dec(() => C4) static method() {} + @dec(() => C4) static get x() { return this.y; } + @dec(() => C4) static set x(v) {} + @dec(() => C4) static y: any; + @dec(() => C4) static accessor z: any; + + @dec(() => C4) method() {} + @dec(() => C4) get x() { return this.y; } + @dec(() => C4) set x(v) {} + @dec(() => C4) y: any; + @dec(() => C4) accessor z: any; +} + +// error +class C5 { + @dec(C5) static method() {} + @dec(C5) static get x() { return this.y; } + @dec(C5) static set x(v) {} + @dec(C5) static y: any; + @dec(C5) static accessor z: any; + + @dec(C5) method() {} + @dec(C5) get x() { return this.y; } + @dec(C5) set x(v) {} + @dec(C5) y: any; + @dec(C5) accessor z: any; +} + +// error +class C6 { + @dec((() => C6)()) static method() {} + @dec((() => C6)()) static get x() { return this.y; } + @dec((() => C6)()) static set x(v) {} + @dec((() => C6)()) static y: any; + @dec((() => C6)()) static accessor z: any; + + @dec((() => C6)()) method() {} + @dec((() => C6)()) get x() { return this.y; } + @dec((() => C6)()) set x(v) {} + @dec((() => C6)()) y: any; + @dec((() => C6)()) accessor z: any; +} diff --git a/tests/cases/compiler/useBeforeDeclaration_classDecorators.2.ts b/tests/cases/compiler/useBeforeDeclaration_classDecorators.2.ts new file mode 100644 index 0000000000000..e3968e99b2d50 --- /dev/null +++ b/tests/cases/compiler/useBeforeDeclaration_classDecorators.2.ts @@ -0,0 +1,74 @@ +// @target: esnext +// @noEmit: true +// @noTypesAndSymbols: true +// @experimentalDecorators: true + +declare const dec: any; + +// ok +@dec(() => C1) class C1 { } + +// error +@dec(C2) class C2 { } + +// error +@dec((() => C3)()) class C3 { } + +// ok +class C4 { + @dec(() => C4) static method() {} + @dec(() => C4) static get x() { return this.y; } + @dec(() => C4) static set x(v) {} + @dec(() => C4) static y: any; + @dec(() => C4) static accessor z: any; + + @dec(() => C4) method() {} + @dec(() => C4) get x() { return this.y; } + @dec(() => C4) set x(v) {} + @dec(() => C4) y: any; + @dec(() => C4) accessor z: any; + + constructor(@dec(() => C4) a: any) {} + static method2(@dec(() => C4) a: any) {} + method2(@dec(() => C4) a: any) {} +} + +// error +class C5 { + @dec(C5) static method() {} + @dec(C5) static get x() { return this.y; } + @dec(C5) static set x(v) {} + @dec(C5) static y: any; + @dec(C5) static accessor z: any; + + @dec(C5) method() {} + @dec(C5) get x() { return this.y; } + @dec(C5) set x(v) {} + @dec(C5) y: any; + @dec(C5) accessor z: any; + + + constructor(@dec(C5) a: any) {} + static method2(@dec(C5) a: any) {} + method2(@dec(C5) a: any) {} +} + +// error +class C6 { + @dec((() => C6)()) static method() {} + @dec((() => C6)()) static get x() { return this.y; } + @dec((() => C6)()) static set x(v) {} + @dec((() => C6)()) static y: any; + @dec((() => C6)()) static accessor z: any; + + @dec((() => C6)()) method() {} + @dec((() => C6)()) get x() { return this.y; } + @dec((() => C6)()) set x(v) {} + @dec((() => C6)()) y: any; + @dec((() => C6)()) accessor z: any; + + + constructor(@dec((() => C6)()) a: any) {} + static method2(@dec((() => C6)()) a: any) {} + method2(@dec((() => C6)()) a: any) {} +}