Disallow yield expressions inside a class
This commit is contained in:
parent
670ad05eec
commit
cb198aa7f2
|
@ -8023,9 +8023,27 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function isYieldExpressionInClass(node: YieldExpression): boolean {
|
||||
let current: Node = node
|
||||
let parent = node.parent;
|
||||
while (parent) {
|
||||
if (isFunctionLike(parent) && current === (<FunctionLikeDeclaration>parent).body) {
|
||||
return false;
|
||||
}
|
||||
else if (current.kind === SyntaxKind.ClassDeclaration || current.kind === SyntaxKind.ClassExpression) {
|
||||
return true;
|
||||
}
|
||||
|
||||
current = parent;
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkYieldExpression(node: YieldExpression): Type {
|
||||
// Grammar checking
|
||||
if (!(node.parserContextFlags & ParserContextFlags.Yield)) {
|
||||
if (!(node.parserContextFlags & ParserContextFlags.Yield) || isYieldExpressionInClass(node)) {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.A_yield_expression_is_only_allowed_in_a_generator_declaration);
|
||||
}
|
||||
|
||||
|
|
|
@ -4010,7 +4010,20 @@ module ts {
|
|||
property.name = name;
|
||||
property.questionToken = questionToken;
|
||||
property.type = parseTypeAnnotation();
|
||||
property.initializer = allowInAnd(parseNonParameterInitializer);
|
||||
|
||||
// For initializers, we always want to allow 'in' expressions. For instance properties specifically,
|
||||
// since they are evaluated inside the constructor, we do *not* want to parse yield expressions,
|
||||
// so we specifically turn the yield context off. The grammar would look something like this:
|
||||
//
|
||||
// MemberVariableDeclaration[Yield]:
|
||||
// AccessibilityModifier_opt PropertyName TypeAnnotation_opt Initialiser_opt[In];
|
||||
// AccessibilityModifier_opt static_opt PropertyName TypeAnnotation_opt Initialiser_opt[In, ?Yield];
|
||||
//
|
||||
// The checker may still error in the static case to explicitly disallow the yield expression.
|
||||
property.initializer = modifiers && modifiers.flags & NodeFlags.Static
|
||||
? allowInAnd(parseNonParameterInitializer)
|
||||
: doOutsideOfContext(ParserContextFlags.Yield | ParserContextFlags.DisallowIn, parseNonParameterInitializer);
|
||||
|
||||
parseSemicolon();
|
||||
return finishNode(property);
|
||||
}
|
||||
|
|
|
@ -530,11 +530,6 @@ module ts {
|
|||
return traverse(body);
|
||||
|
||||
function traverse(node: Node): void {
|
||||
// Yield expressions may occur in decorators
|
||||
if (node.decorators) {
|
||||
forEach(node.decorators, traverse);
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.YieldExpression:
|
||||
visitor(<YieldExpression>node);
|
||||
|
@ -546,18 +541,17 @@ module ts {
|
|||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
// These are not allowed inside a generator now, but eventually they may be allowed
|
||||
// as local types. Regardless, any yield statements contained within them should be
|
||||
// skipped in this traversal.
|
||||
return;
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
// A class declaration/expression may extend a yield expression
|
||||
forEach((<ClassDeclaration>node).heritageClauses, traverse);
|
||||
return;
|
||||
default:
|
||||
if (isFunctionLike(node)) {
|
||||
let name = (<FunctionLikeDeclaration>node).name;
|
||||
if (name && name.kind === SyntaxKind.ComputedPropertyName) {
|
||||
// Note that we will not include methods/accessors of a class because they would require
|
||||
// first descending into the class. This is by design.
|
||||
traverse((<ComputedPropertyName>name).expression);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck55.ts(2,19): error TS9003: 'class' expressions are not currently supported.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck55.ts (1 errors) ====
|
||||
function* g() {
|
||||
var x = class C extends (yield) {};
|
||||
~
|
||||
!!! error TS9003: 'class' expressions are not currently supported.
|
||||
}
|
11
tests/baselines/reference/generatorTypeCheck55.js
Normal file
11
tests/baselines/reference/generatorTypeCheck55.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
//// [generatorTypeCheck55.ts]
|
||||
function* g() {
|
||||
var x = class C extends (yield) {};
|
||||
}
|
||||
|
||||
//// [generatorTypeCheck55.js]
|
||||
function* g() {
|
||||
var x = class C extends (yield) {
|
||||
}
|
||||
;
|
||||
}
|
16
tests/baselines/reference/generatorTypeCheck56.errors.txt
Normal file
16
tests/baselines/reference/generatorTypeCheck56.errors.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck56.ts(2,19): error TS9003: 'class' expressions are not currently supported.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck56.ts(3,11): error TS1163: A 'yield' expression is only allowed in a generator declaration.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck56.ts (2 errors) ====
|
||||
function* g() {
|
||||
var x = class C {
|
||||
~
|
||||
!!! error TS9003: 'class' expressions are not currently supported.
|
||||
*[yield 0]() {
|
||||
~~~~~
|
||||
!!! error TS1163: A 'yield' expression is only allowed in a generator declaration.
|
||||
yield 0;
|
||||
}
|
||||
};
|
||||
}
|
18
tests/baselines/reference/generatorTypeCheck56.js
Normal file
18
tests/baselines/reference/generatorTypeCheck56.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
//// [generatorTypeCheck56.ts]
|
||||
function* g() {
|
||||
var x = class C {
|
||||
*[yield 0]() {
|
||||
yield 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//// [generatorTypeCheck56.js]
|
||||
function* g() {
|
||||
var x = class C {
|
||||
*[yield 0]() {
|
||||
yield 0;
|
||||
}
|
||||
}
|
||||
;
|
||||
}
|
14
tests/baselines/reference/generatorTypeCheck57.errors.txt
Normal file
14
tests/baselines/reference/generatorTypeCheck57.errors.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck57.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck57.ts(3,13): error TS1163: A 'yield' expression is only allowed in a generator declaration.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck57.ts (2 errors) ====
|
||||
function* g() {
|
||||
class C {
|
||||
~
|
||||
!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration.
|
||||
x = yield 0;
|
||||
~~~~~
|
||||
!!! error TS1163: A 'yield' expression is only allowed in a generator declaration.
|
||||
};
|
||||
}
|
16
tests/baselines/reference/generatorTypeCheck57.js
Normal file
16
tests/baselines/reference/generatorTypeCheck57.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
//// [generatorTypeCheck57.ts]
|
||||
function* g() {
|
||||
class C {
|
||||
x = yield 0;
|
||||
};
|
||||
}
|
||||
|
||||
//// [generatorTypeCheck57.js]
|
||||
function* g() {
|
||||
class C {
|
||||
constructor() {
|
||||
this.x = yield 0;
|
||||
}
|
||||
}
|
||||
;
|
||||
}
|
14
tests/baselines/reference/generatorTypeCheck58.errors.txt
Normal file
14
tests/baselines/reference/generatorTypeCheck58.errors.txt
Normal file
|
@ -0,0 +1,14 @@
|
|||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck58.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck58.ts(3,20): error TS1163: A 'yield' expression is only allowed in a generator declaration.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck58.ts (2 errors) ====
|
||||
function* g() {
|
||||
class C {
|
||||
~
|
||||
!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration.
|
||||
static x = yield 0;
|
||||
~~~~~
|
||||
!!! error TS1163: A 'yield' expression is only allowed in a generator declaration.
|
||||
};
|
||||
}
|
14
tests/baselines/reference/generatorTypeCheck58.js
Normal file
14
tests/baselines/reference/generatorTypeCheck58.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
//// [generatorTypeCheck58.ts]
|
||||
function* g() {
|
||||
class C {
|
||||
static x = yield 0;
|
||||
};
|
||||
}
|
||||
|
||||
//// [generatorTypeCheck58.js]
|
||||
function* g() {
|
||||
class C {
|
||||
}
|
||||
C.x = yield 0;
|
||||
;
|
||||
}
|
15
tests/baselines/reference/generatorTypeCheck59.errors.txt
Normal file
15
tests/baselines/reference/generatorTypeCheck59.errors.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts(3,11): error TS1163: A 'yield' expression is only allowed in a generator declaration.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck59.ts (2 errors) ====
|
||||
function* g() {
|
||||
class C {
|
||||
~
|
||||
!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration.
|
||||
@(yield "")
|
||||
~~~~~
|
||||
!!! error TS1163: A 'yield' expression is only allowed in a generator declaration.
|
||||
m() { }
|
||||
};
|
||||
}
|
27
tests/baselines/reference/generatorTypeCheck59.js
Normal file
27
tests/baselines/reference/generatorTypeCheck59.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
//// [generatorTypeCheck59.ts]
|
||||
function* g() {
|
||||
class C {
|
||||
@(yield "")
|
||||
m() { }
|
||||
};
|
||||
}
|
||||
|
||||
//// [generatorTypeCheck59.js]
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
|
||||
switch (arguments.length) {
|
||||
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
|
||||
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
|
||||
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
|
||||
}
|
||||
};
|
||||
function* g() {
|
||||
class C {
|
||||
m() { }
|
||||
}
|
||||
Object.defineProperty(C.prototype, "m",
|
||||
__decorate([
|
||||
(yield "")
|
||||
], C.prototype, "m", Object.getOwnPropertyDescriptor(C.prototype, "m")));
|
||||
;
|
||||
}
|
12
tests/baselines/reference/generatorTypeCheck60.errors.txt
Normal file
12
tests/baselines/reference/generatorTypeCheck60.errors.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts(2,11): error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts(2,21): error TS9002: Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck60.ts (2 errors) ====
|
||||
function* g() {
|
||||
class C extends (yield) {};
|
||||
~
|
||||
!!! error TS9004: 'class' declarations are only supported directly inside a module or as a top level declaration.
|
||||
~~~~~~~
|
||||
!!! error TS9002: Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses.
|
||||
}
|
11
tests/baselines/reference/generatorTypeCheck60.js
Normal file
11
tests/baselines/reference/generatorTypeCheck60.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
//// [generatorTypeCheck60.ts]
|
||||
function* g() {
|
||||
class C extends (yield) {};
|
||||
}
|
||||
|
||||
//// [generatorTypeCheck60.js]
|
||||
function* g() {
|
||||
class C extends (yield) {
|
||||
}
|
||||
;
|
||||
}
|
22
tests/baselines/reference/generatorTypeCheck61.errors.txt
Normal file
22
tests/baselines/reference/generatorTypeCheck61.errors.txt
Normal file
|
@ -0,0 +1,22 @@
|
|||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,5): error TS1129: Statement expected.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,12): error TS1146: Declaration expected.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,13): error TS1005: ')' expected.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(2,14): error TS1005: ';' expected.
|
||||
tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts(4,1): error TS1128: Declaration or statement expected.
|
||||
|
||||
|
||||
==== tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck61.ts (5 errors) ====
|
||||
function * g() {
|
||||
@(yield 0)
|
||||
~
|
||||
!!! error TS1129: Statement expected.
|
||||
|
||||
!!! error TS1146: Declaration expected.
|
||||
~
|
||||
!!! error TS1005: ')' expected.
|
||||
~
|
||||
!!! error TS1005: ';' expected.
|
||||
class C {};
|
||||
}
|
||||
~
|
||||
!!! error TS1128: Declaration or statement expected.
|
12
tests/baselines/reference/generatorTypeCheck61.js
Normal file
12
tests/baselines/reference/generatorTypeCheck61.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
//// [generatorTypeCheck61.ts]
|
||||
function * g() {
|
||||
@(yield 0)
|
||||
class C {};
|
||||
}
|
||||
|
||||
//// [generatorTypeCheck61.js]
|
||||
function* g() { }
|
||||
0;
|
||||
class C {
|
||||
}
|
||||
;
|
|
@ -0,0 +1,4 @@
|
|||
//@target: ES6
|
||||
function* g() {
|
||||
var x = class C extends (yield) {};
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
//@target: ES6
|
||||
function* g() {
|
||||
var x = class C {
|
||||
*[yield 0]() {
|
||||
yield 0;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
//@target: ES6
|
||||
function* g() {
|
||||
class C {
|
||||
x = yield 0;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
//@target: ES6
|
||||
function* g() {
|
||||
class C {
|
||||
static x = yield 0;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
//@target: ES6
|
||||
function* g() {
|
||||
class C {
|
||||
@(yield "")
|
||||
m() { }
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
//@target: ES6
|
||||
function* g() {
|
||||
class C extends (yield) {};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
//@target: ES6
|
||||
function * g() {
|
||||
@(yield 0)
|
||||
class C {};
|
||||
}
|
Loading…
Reference in a new issue