property is used before its initialization: check more nodes

Fixes: #29125
This commit is contained in:
Klaus Meinhardt 2018-12-23 23:13:46 +01:00
parent b8def16e92
commit a769c35484
11 changed files with 422 additions and 22 deletions

View file

@ -19094,7 +19094,19 @@ namespace ts {
case SyntaxKind.PropertyDeclaration:
return true;
case SyntaxKind.PropertyAssignment:
// We might be in `a = { b: this.b }`, so keep looking. See `tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts`.
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.SpreadAssignment:
case SyntaxKind.ComputedPropertyName:
case SyntaxKind.TemplateSpan:
case SyntaxKind.JsxExpression:
case SyntaxKind.JsxAttribute:
case SyntaxKind.JsxAttributes:
case SyntaxKind.JsxSpreadAttribute:
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.HeritageClause:
return false;
default:
return isExpressionNode(node) ? false : "quit";

View file

@ -0,0 +1,38 @@
tests/cases/compiler/useBeforeDeclaration_jsx.tsx(6,19): error TS2729: Property 'z' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_jsx.tsx(7,19): error TS2729: Property 'z' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_jsx.tsx(8,28): error TS2729: Property 'x' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_jsx.tsx(9,28): error TS2729: Property 'y' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_jsx.tsx(10,25): error TS2729: Property 'y' is used before its initialization.
==== tests/cases/compiler/useBeforeDeclaration_jsx.tsx (5 errors) ====
namespace JSX {
export interface Element {}
}
class C {
static a = <C.z></C.z>;
~
!!! error TS2729: Property 'z' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:13:12: 'z' is declared here.
static b = <C.z/>;
~
!!! error TS2729: Property 'z' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:13:12: 'z' is declared here.
static c = <span {...C.x}></span>;
~
!!! error TS2729: Property 'x' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:11:12: 'x' is declared here.
static d = <span id={C.y}></span>;
~
!!! error TS2729: Property 'y' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:12:12: 'y' is declared here.
static e = <span>{C.y}</span>;
~
!!! error TS2729: Property 'y' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_jsx.tsx:12:12: 'y' is declared here.
static x = {};
static y = '';
static z = () => <b></b>;
}

View file

@ -0,0 +1,28 @@
//// [useBeforeDeclaration_jsx.tsx]
namespace JSX {
export interface Element {}
}
class C {
static a = <C.z></C.z>;
static b = <C.z/>;
static c = <span {...C.x}></span>;
static d = <span id={C.y}></span>;
static e = <span>{C.y}</span>;
static x = {};
static y = '';
static z = () => <b></b>;
}
//// [useBeforeDeclaration_jsx.jsx]
class C {
}
C.a = <C.z></C.z>;
C.b = <C.z />;
C.c = <span {...C.x}></span>;
C.d = <span id={C.y}></span>;
C.e = <span>{C.y}</span>;
C.x = {};
C.y = '';
C.z = () => <b></b>;

View file

@ -0,0 +1,55 @@
=== tests/cases/compiler/useBeforeDeclaration_jsx.tsx ===
namespace JSX {
>JSX : Symbol(JSX, Decl(useBeforeDeclaration_jsx.tsx, 0, 0))
export interface Element {}
>Element : Symbol(Element, Decl(useBeforeDeclaration_jsx.tsx, 0, 15))
}
class C {
>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1))
static a = <C.z></C.z>;
>a : Symbol(C.a, Decl(useBeforeDeclaration_jsx.tsx, 4, 9))
>C.z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18))
>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1))
>z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18))
>C.z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18))
>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1))
>z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18))
static b = <C.z/>;
>b : Symbol(C.b, Decl(useBeforeDeclaration_jsx.tsx, 5, 27))
>C.z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18))
>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1))
>z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18))
static c = <span {...C.x}></span>;
>c : Symbol(C.c, Decl(useBeforeDeclaration_jsx.tsx, 6, 22))
>C.x : Symbol(C.x, Decl(useBeforeDeclaration_jsx.tsx, 9, 34))
>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1))
>x : Symbol(C.x, Decl(useBeforeDeclaration_jsx.tsx, 9, 34))
static d = <span id={C.y}></span>;
>d : Symbol(C.d, Decl(useBeforeDeclaration_jsx.tsx, 7, 38))
>id : Symbol(id, Decl(useBeforeDeclaration_jsx.tsx, 8, 20))
>C.y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18))
>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1))
>y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18))
static e = <span>{C.y}</span>;
>e : Symbol(C.e, Decl(useBeforeDeclaration_jsx.tsx, 8, 38))
>C.y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18))
>C : Symbol(C, Decl(useBeforeDeclaration_jsx.tsx, 2, 1))
>y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18))
static x = {};
>x : Symbol(C.x, Decl(useBeforeDeclaration_jsx.tsx, 9, 34))
static y = '';
>y : Symbol(C.y, Decl(useBeforeDeclaration_jsx.tsx, 10, 18))
static z = () => <b></b>;
>z : Symbol(C.z, Decl(useBeforeDeclaration_jsx.tsx, 11, 18))
}

View file

@ -0,0 +1,69 @@
=== tests/cases/compiler/useBeforeDeclaration_jsx.tsx ===
namespace JSX {
export interface Element {}
}
class C {
>C : C
static a = <C.z></C.z>;
>a : JSX.Element
><C.z></C.z> : JSX.Element
>C.z : () => JSX.Element
>C : typeof C
>z : () => JSX.Element
>C.z : () => JSX.Element
>C : typeof C
>z : () => JSX.Element
static b = <C.z/>;
>b : JSX.Element
><C.z/> : JSX.Element
>C.z : () => JSX.Element
>C : typeof C
>z : () => JSX.Element
static c = <span {...C.x}></span>;
>c : JSX.Element
><span {...C.x}></span> : JSX.Element
>span : any
>C.x : {}
>C : typeof C
>x : {}
>span : any
static d = <span id={C.y}></span>;
>d : JSX.Element
><span id={C.y}></span> : JSX.Element
>span : any
>id : string
>C.y : string
>C : typeof C
>y : string
>span : any
static e = <span>{C.y}</span>;
>e : JSX.Element
><span>{C.y}</span> : JSX.Element
>span : any
>C.y : string
>C : typeof C
>y : string
>span : any
static x = {};
>x : {}
>{} : {}
static y = '';
>y : string
>'' : ""
static z = () => <b></b>;
>z : () => JSX.Element
>() => <b></b> : () => JSX.Element
><b></b> : JSX.Element
>b : any
>b : any
}

View file

@ -1,12 +1,44 @@
tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,27): error TS2729: Property 'b' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,38): error TS2729: Property 'c' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,47): error TS2729: Property 'b' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(2,59): error TS2729: Property 'c' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(8,32): error TS2729: Property 'B' is used before its initialization.
tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts(13,12): error TS2729: Property 'D' is used before its initialization.
==== tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts (1 errors) ====
==== tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts (6 errors) ====
export class C {
public a = { b: this.b };
public a = { b: this.b, ...this.c, [this.b]: `${this.c}`};
~
!!! error TS2729: Property 'b' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:3:13: 'b' is declared here.
~
!!! error TS2729: Property 'c' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:4:12: 'c' is declared here.
~
!!! error TS2729: Property 'b' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:3:13: 'b' is declared here.
~
!!! error TS2729: Property 'c' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:4:12: 'c' is declared here.
private b = 0;
public c = { c: this.b };
}
class D {
static A = class extends D.B {
~
!!! error TS2729: Property 'B' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:11:12: 'B' is declared here.
[D.D]() {} // should be an error
}
static B = class {}
static C = {
[D.D]: 1,
~
!!! error TS2729: Property 'D' is used before its initialization.
!!! related TS2728 tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts:16:12: 'D' is declared here.
...{get [D.D]() {return 0;}} // should be an error
};
static D = '';
}

View file

@ -1,18 +1,37 @@
//// [useBeforeDeclaration_propertyAssignment.ts]
export class C {
public a = { b: this.b };
public a = { b: this.b, ...this.c, [this.b]: `${this.c}`};
private b = 0;
public c = { c: this.b };
}
class D {
static A = class extends D.B {
[D.D]() {} // should be an error
}
static B = class {}
static C = {
[D.D]: 1,
...{get [D.D]() {return 0;}} // should be an error
};
static D = '';
}
//// [useBeforeDeclaration_propertyAssignment.js]
"use strict";
exports.__esModule = true;
var C = /** @class */ (function () {
function C() {
this.a = { b: this.b };
export class C {
constructor() {
this.a = Object.assign({ b: this.b }, this.c, { [this.b]: `${this.c}` });
this.b = 0;
this.c = { c: this.b };
}
return C;
}());
exports.C = C;
}
class D {
}
D.A = class extends D.B {
[D.D]() { } // should be an error
};
D.B = class {
};
D.C = Object.assign({ [D.D]: 1 }, { get [D.D]() { return 0; } } // should be an error
);
D.D = '';

View file

@ -2,14 +2,68 @@
export class C {
>C : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0))
public a = { b: this.b };
public a = { b: this.b, ...this.c, [this.b]: `${this.c}`};
>a : Symbol(C.a, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 16))
>b : Symbol(b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 17))
>this.b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 30))
>this.b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63))
>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0))
>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 30))
>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63))
>this.c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18))
>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0))
>c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18))
>[this.b] : Symbol([this.b], Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 39))
>this.b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63))
>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0))
>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63))
>this.c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18))
>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0))
>c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18))
private b = 0;
>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 30))
>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63))
public c = { c: this.b };
>c : Symbol(C.c, Decl(useBeforeDeclaration_propertyAssignment.ts, 2, 18))
>c : Symbol(c, Decl(useBeforeDeclaration_propertyAssignment.ts, 3, 16))
>this.b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63))
>this : Symbol(C, Decl(useBeforeDeclaration_propertyAssignment.ts, 0, 0))
>b : Symbol(C.b, Decl(useBeforeDeclaration_propertyAssignment.ts, 1, 63))
}
class D {
>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1))
static A = class extends D.B {
>A : Symbol(D.A, Decl(useBeforeDeclaration_propertyAssignment.ts, 6, 9))
>D.B : Symbol(D.B, Decl(useBeforeDeclaration_propertyAssignment.ts, 9, 5))
>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1))
>B : Symbol(D.B, Decl(useBeforeDeclaration_propertyAssignment.ts, 9, 5))
[D.D]() {} // should be an error
>[D.D] : Symbol((Anonymous class)[D.D], Decl(useBeforeDeclaration_propertyAssignment.ts, 7, 34))
>D.D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6))
>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1))
>D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6))
}
static B = class {}
>B : Symbol(D.B, Decl(useBeforeDeclaration_propertyAssignment.ts, 9, 5))
static C = {
>C : Symbol(D.C, Decl(useBeforeDeclaration_propertyAssignment.ts, 10, 23))
[D.D]: 1,
>[D.D] : Symbol([D.D], Decl(useBeforeDeclaration_propertyAssignment.ts, 11, 16))
>D.D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6))
>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1))
>D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6))
...{get [D.D]() {return 0;}} // should be an error
>[D.D] : Symbol([D.D], Decl(useBeforeDeclaration_propertyAssignment.ts, 13, 12))
>D.D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6))
>D : Symbol(D, Decl(useBeforeDeclaration_propertyAssignment.ts, 4, 1))
>D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6))
};
static D = '';
>D : Symbol(D.D, Decl(useBeforeDeclaration_propertyAssignment.ts, 14, 6))
}

View file

@ -2,16 +2,79 @@
export class C {
>C : C
public a = { b: this.b };
>a : { b: number; }
>{ b: this.b } : { b: number; }
public a = { b: this.b, ...this.c, [this.b]: `${this.c}`};
>a : { c: number; b: number; }
>{ b: this.b, ...this.c, [this.b]: `${this.c}`} : { c: number; b: number; }
>b : number
>this.b : number
>this : this
>b : number
>this.c : { c: number; }
>this : this
>c : { c: number; }
>[this.b] : string
>this.b : number
>this : this
>b : number
>`${this.c}` : string
>this.c : { c: number; }
>this : this
>c : { c: number; }
private b = 0;
>b : number
>0 : 0
public c = { c: this.b };
>c : { c: number; }
>{ c: this.b } : { c: number; }
>c : number
>this.b : number
>this : this
>b : number
}
class D {
>D : D
static A = class extends D.B {
>A : typeof (Anonymous class)
>class extends D.B { [D.D]() {} // should be an error } : typeof (Anonymous class)
>D.B : (Anonymous class)
>D : typeof D
>B : typeof (Anonymous class)
[D.D]() {} // should be an error
>[D.D] : () => void
>D.D : string
>D : typeof D
>D : string
}
static B = class {}
>B : typeof (Anonymous class)
>class {} : typeof (Anonymous class)
static C = {
>C : { [x: string]: number; }
>{ [D.D]: 1, ...{get [D.D]() {return 0;}} // should be an error } : { [x: string]: number; }
[D.D]: 1,
>[D.D] : number
>D.D : string
>D : typeof D
>D : string
>1 : 1
...{get [D.D]() {return 0;}} // should be an error
>{get [D.D]() {return 0;}} : { [x: string]: number; }
>[D.D] : number
>D.D : string
>D : typeof D
>D : string
>0 : 0
};
static D = '';
>D : string
>'' : ""
}

View file

@ -0,0 +1,16 @@
// @jsx: preserve
// @target: ES6
namespace JSX {
export interface Element {}
}
class C {
static a = <C.z></C.z>;
static b = <C.z/>;
static c = <span {...C.x}></span>;
static d = <span id={C.y}></span>;
static e = <span>{C.y}</span>;
static x = {};
static y = '';
static z = () => <b></b>;
}

View file

@ -1,4 +1,18 @@
// @target: ES6
export class C {
public a = { b: this.b };
public a = { b: this.b, ...this.c, [this.b]: `${this.c}`};
private b = 0;
public c = { c: this.b };
}
class D {
static A = class extends D.B {
[D.D]() {} // should be an error
}
static B = class {}
static C = {
[D.D]: 1,
...{get [D.D]() {return 0;}} // should be an error
};
static D = '';
}