Support TS 4.3 override syntax in class (#13097)
* support TS 4.3 `override` syntax in class * fix types * fix types * tweak error message * update TypeScript commit * split tests * add more tests * update allowlist * disallow `override` with `declare` * disallow `override` in non-sub class * update TypeScript allowlist * rename error message key * add more tests
This commit is contained in:
@@ -128,6 +128,8 @@ export const ErrorMessages = makeErrorTemplates(
|
||||
"constructors in/after an Optional Chain are not allowed",
|
||||
OptionalChainingNoTemplate:
|
||||
"Tagged Template Literals are not allowed in optionalChain",
|
||||
OverrideOnConstructor:
|
||||
"'override' modifier cannot appear on a constructor declaration.",
|
||||
ParamDupe: "Argument name clash",
|
||||
PatternHasAccessor: "Object pattern can't contain getter or setter",
|
||||
PatternHasMethod: "Object pattern can't contain methods",
|
||||
|
||||
@@ -1205,15 +1205,12 @@ export default class StatementParser extends ExpressionParser {
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/#prod-ClassBody
|
||||
parseClassBody(
|
||||
constructorAllowsSuper: boolean,
|
||||
oldStrict: boolean,
|
||||
): N.ClassBody {
|
||||
parseClassBody(hadSuperClass: boolean, oldStrict: boolean): N.ClassBody {
|
||||
this.classScope.enter();
|
||||
|
||||
const state: N.ParseClassMemberState = {
|
||||
constructorAllowsSuper,
|
||||
hadConstructor: false,
|
||||
hadSuperClass,
|
||||
};
|
||||
let decorators: N.Decorator[] = [];
|
||||
const classBody: N.ClassBody = this.startNode();
|
||||
@@ -1400,8 +1397,11 @@ export default class StatementParser extends ExpressionParser {
|
||||
if (state.hadConstructor && !this.hasPlugin("typescript")) {
|
||||
this.raise(key.start, Errors.DuplicateConstructor);
|
||||
}
|
||||
if (isConstructor && this.hasPlugin("typescript") && member.override) {
|
||||
this.raise(key.start, Errors.OverrideOnConstructor);
|
||||
}
|
||||
state.hadConstructor = true;
|
||||
allowsDirectSuper = state.constructorAllowsSuper;
|
||||
allowsDirectSuper = state.hadSuperClass;
|
||||
}
|
||||
|
||||
this.pushClassMethod(
|
||||
|
||||
@@ -41,6 +41,7 @@ type TsModifier =
|
||||
| "abstract"
|
||||
| "declare"
|
||||
| "static"
|
||||
| "override"
|
||||
| N.Accessibility;
|
||||
|
||||
function nonNull<T>(x: ?T): T {
|
||||
@@ -86,12 +87,15 @@ const TSErrors = makeErrorTemplates(
|
||||
ExpectedAmbientAfterExportDeclare:
|
||||
"'export declare' must be followed by an ambient declaration.",
|
||||
ImportAliasHasImportType: "An import alias can not use 'import type'",
|
||||
IncompatibleModifiers: "'%0' modifier cannot be used with '%1' modifier.",
|
||||
IndexSignatureHasAbstract:
|
||||
"Index signatures cannot have the 'abstract' modifier",
|
||||
IndexSignatureHasAccessibility:
|
||||
"Index signatures cannot have an accessibility modifier ('%0')",
|
||||
IndexSignatureHasDeclare:
|
||||
"Index signatures cannot have the 'declare' modifier",
|
||||
IndexSignatureHasOverride:
|
||||
"'override' modifier cannot appear on an index signature.",
|
||||
IndexSignatureHasStatic:
|
||||
"Index signatures cannot have the 'static' modifier",
|
||||
InvalidModifierOnTypeMember:
|
||||
@@ -107,6 +111,8 @@ const TSErrors = makeErrorTemplates(
|
||||
"'abstract' modifier can only appear on a class, method, or property declaration.",
|
||||
OptionalTypeBeforeRequired:
|
||||
"A required element cannot follow an optional element.",
|
||||
OverrideNotInSubClass:
|
||||
"This member cannot have an 'override' modifier because its containing class does not extend another class.",
|
||||
PatternIsOptional:
|
||||
"A binding pattern parameter cannot be optional in an implementation signature.",
|
||||
PrivateElementHasAbstract:
|
||||
@@ -257,6 +263,16 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
"static",
|
||||
"readonly",
|
||||
);
|
||||
} else if (
|
||||
(modified.declare && modifier === "override") ||
|
||||
(modified.override && modifier === "declare")
|
||||
) {
|
||||
this.raise(
|
||||
startPos,
|
||||
TSErrors.IncompatibleModifiers,
|
||||
"declare",
|
||||
"override",
|
||||
);
|
||||
}
|
||||
modified[modifier] = true;
|
||||
}
|
||||
@@ -622,7 +638,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.tsParseModifiers(
|
||||
node,
|
||||
["readonly"],
|
||||
["declare", "abstract", "private", "protected", "public", "static"],
|
||||
[
|
||||
"declare",
|
||||
"abstract",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"static",
|
||||
"override",
|
||||
],
|
||||
TSErrors.InvalidModifierOnTypeMember,
|
||||
);
|
||||
|
||||
@@ -2223,6 +2247,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
"private",
|
||||
"public",
|
||||
"protected",
|
||||
"override",
|
||||
]);
|
||||
|
||||
const callParseClassMember = () => {
|
||||
@@ -2246,6 +2271,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
"readonly",
|
||||
"declare",
|
||||
"static",
|
||||
"override",
|
||||
]);
|
||||
|
||||
if (isStatic) {
|
||||
@@ -2269,6 +2295,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
if ((member: any).declare) {
|
||||
this.raise(member.start, TSErrors.IndexSignatureHasDeclare);
|
||||
}
|
||||
if ((member: any).override) {
|
||||
this.raise(member.start, TSErrors.IndexSignatureHasOverride);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -2277,6 +2306,19 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.raise(member.start, TSErrors.NonAbstractClassHasAbstractMethod);
|
||||
}
|
||||
|
||||
if ((member: any).override) {
|
||||
if (isStatic) {
|
||||
this.raise(
|
||||
member.start,
|
||||
TSErrors.IncompatibleModifiers,
|
||||
"static",
|
||||
"override",
|
||||
);
|
||||
} else if (!state.hadSuperClass) {
|
||||
this.raise(member.start, TSErrors.OverrideNotInSubClass);
|
||||
}
|
||||
}
|
||||
|
||||
/*:: invariant(member.type !== "TSIndexSignature") */
|
||||
|
||||
super.parseClassMemberWithIsStatic(classBody, member, state, isStatic);
|
||||
|
||||
@@ -730,6 +730,7 @@ export type ClassMemberBase = NodeBase &
|
||||
computed: boolean,
|
||||
// TypeScript only:
|
||||
accessibility?: ?Accessibility,
|
||||
override?: ?true,
|
||||
abstract?: ?true,
|
||||
optional?: ?true,
|
||||
};
|
||||
@@ -807,6 +808,7 @@ export type ClassPrivateProperty = NodeBase & {
|
||||
optional?: true,
|
||||
definite?: true,
|
||||
readonly?: true,
|
||||
override?: true,
|
||||
};
|
||||
|
||||
export type OptClassDeclaration = ClassBase &
|
||||
@@ -1536,5 +1538,5 @@ export type ParseSubscriptState = {
|
||||
|
||||
export type ParseClassMemberState = {|
|
||||
hadConstructor: boolean,
|
||||
constructorAllowsSuper: boolean,
|
||||
hadSuperClass: boolean,
|
||||
|};
|
||||
|
||||
Reference in New Issue
Block a user