mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-16 07:13:43 -05:00
Permit abstract modifier on class expressions
This commit is contained in:
@@ -38980,7 +38980,6 @@ namespace ts {
|
||||
if (flags & ModifierFlags.Abstract) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract");
|
||||
}
|
||||
// An abstract modifier is permitted on a class expression in a 'typeof abstract class {}' type
|
||||
if (node.kind !== SyntaxKind.ClassDeclaration && node.kind !== SyntaxKind.ClassExpression) {
|
||||
if (node.kind !== SyntaxKind.MethodDeclaration &&
|
||||
node.kind !== SyntaxKind.PropertyDeclaration &&
|
||||
@@ -38988,7 +38987,7 @@ namespace ts {
|
||||
node.kind !== SyntaxKind.SetAccessor) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration);
|
||||
}
|
||||
if (!(node.parent.kind === SyntaxKind.ClassDeclaration && hasSyntacticModifier(node.parent, ModifierFlags.Abstract))) {
|
||||
if (!((node.parent.kind === SyntaxKind.ClassDeclaration || node.parent.kind === SyntaxKind.ClassExpression) && hasSyntacticModifier(node.parent, ModifierFlags.Abstract))) {
|
||||
return grammarErrorOnNode(modifier, Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class);
|
||||
}
|
||||
if (flags & ModifierFlags.Static) {
|
||||
@@ -39096,7 +39095,6 @@ namespace ts {
|
||||
return nodeHasAnyModifiersExcept(node, SyntaxKind.AsyncKeyword);
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
// An abstract modifier is permitted on a class expression in a 'typeof abstract class {}' type
|
||||
return nodeHasAnyModifiersExcept(node, SyntaxKind.AbstractKeyword);
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.VariableStatement:
|
||||
|
||||
@@ -2861,22 +2861,14 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isStartOfTypeofClassExpression() {
|
||||
return token() === SyntaxKind.ClassKeyword ||
|
||||
token() === SyntaxKind.AbstractKeyword && lookAhead(() => nextToken() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak());
|
||||
}
|
||||
|
||||
function parseTypeofClassExpression(): ClassExpression {
|
||||
const pos = getNodePos();
|
||||
const hasJSDoc = hasPrecedingJSDocComment();
|
||||
const modifiers = parseModifiers();
|
||||
return <ClassExpression>parseClassDeclarationOrExpression(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.ClassExpression);
|
||||
return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine);
|
||||
}
|
||||
|
||||
function parseTypeQuery(): TypeQueryNode {
|
||||
const pos = getNodePos();
|
||||
parseExpected(SyntaxKind.TypeOfKeyword);
|
||||
return finishNode(factory.createTypeQueryNode(isStartOfTypeofClassExpression() ?
|
||||
doInsideOfContext(NodeFlags.Ambient, parseTypeofClassExpression) :
|
||||
doInsideOfContext(NodeFlags.Ambient, parseClassExpression) :
|
||||
parseEntityName(/*allowReservedWords*/ true)), pos);
|
||||
}
|
||||
|
||||
@@ -5323,6 +5315,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
return parseFunctionExpression();
|
||||
case SyntaxKind.AbstractKeyword:
|
||||
if (!lookAhead(nextTokenIsClassKeywordOnSameLine)) {
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
case SyntaxKind.ClassKeyword:
|
||||
return parseClassExpression();
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
@@ -6654,7 +6651,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function parseClassExpression(): ClassExpression {
|
||||
return <ClassExpression>parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined, SyntaxKind.ClassExpression);
|
||||
const pos = getNodePos();
|
||||
const hasJSDoc = hasPrecedingJSDocComment();
|
||||
const modifiers = parseModifiers();
|
||||
return <ClassExpression>parseClassDeclarationOrExpression(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.ClassExpression);
|
||||
}
|
||||
|
||||
function parseClassDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ClassDeclaration {
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace ts {
|
||||
|
||||
function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): readonly Node[] | undefined {
|
||||
// Types of node whose children might have modifiers.
|
||||
const container = declaration.parent as ModuleBlock | SourceFile | Block | CaseClause | DefaultClause | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | ObjectTypeDeclaration | ObjectLiteralExpression;
|
||||
const container = declaration.parent;
|
||||
switch (container.kind) {
|
||||
case SyntaxKind.ModuleBlock:
|
||||
case SyntaxKind.SourceFile:
|
||||
@@ -216,22 +216,21 @@ namespace ts {
|
||||
return [...declaration.members, declaration];
|
||||
}
|
||||
else {
|
||||
return container.statements;
|
||||
return (<ModuleBlock | SourceFile | Block | CaseClause | DefaultClause>container).statements;
|
||||
}
|
||||
case SyntaxKind.Constructor:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return [...container.parameters, ...(isClassLike(container.parent) ? container.parent.members : [])];
|
||||
return [...(<ConstructorDeclaration | MethodDeclaration | FunctionDeclaration>container).parameters, ...(isClassLike(container.parent) ? container.parent.members : [])];
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
const nodes = container.members;
|
||||
|
||||
const nodes = (<ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeLiteralNode>container).members;
|
||||
// If we're an accessibility modifier, we're in an instance member and should search
|
||||
// the constructor's parameter list for instance members as well.
|
||||
if (modifierFlag & (ModifierFlags.AccessibilityModifier | ModifierFlags.Readonly)) {
|
||||
const constructor = find(container.members, isConstructorDeclaration);
|
||||
const constructor = find(nodes, isConstructorDeclaration);
|
||||
if (constructor) {
|
||||
return [...nodes, ...constructor.parameters];
|
||||
}
|
||||
@@ -240,13 +239,11 @@ namespace ts {
|
||||
return [...nodes, container];
|
||||
}
|
||||
return nodes;
|
||||
|
||||
// Syntactically invalid positions that the parser might produce anyway
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
return undefined;
|
||||
|
||||
default:
|
||||
Debug.assertNever(container, "Invalid container kind.");
|
||||
if (modifierFlag & ModifierFlags.Abstract && isClassExpression(declaration)) {
|
||||
return [...declaration.members, declaration];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user