mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Disallow yield expressions inside a class
This commit is contained in:
+19
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+14
-1
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user