Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support TS 4.3 override syntax in class #13097

Merged
merged 13 commits into from Apr 7, 2021
2 changes: 1 addition & 1 deletion Makefile
@@ -1,6 +1,6 @@
FLOW_COMMIT = a1f9a4c709dcebb27a5084acf47755fbae699c25
TEST262_COMMIT = 31126581e7290f9233c29cefd93f66c6ac78f1c9
TYPESCRIPT_COMMIT = 41dc625b0a609eb294b975dd92675e72b2b3fdec
TYPESCRIPT_COMMIT = dd1ef88d016dc40a145eafc0a1169e7f0a4a9ebe

# Fix color output until TravisCI fixes https://github.com/travis-ci/travis-ci/issues/7967
export FORCE_COLOR = true
Expand Down
4 changes: 4 additions & 0 deletions packages/babel-generator/src/generators/typescript.ts
Expand Up @@ -644,6 +644,10 @@ export function tsPrintClassMemberModifiers(this: Printer, node: any, isField) {
this.word("declare");
this.space();
}
if (node.override) {
this.word("override");
this.space();
}
if (node.accessibility) {
this.word(node.accessibility);
this.space();
Expand Down
@@ -0,0 +1,8 @@
class MyClass extends BaseClass {
override show() {}
override public show() {}
public override show() {}
override size = 5;
override readonly size = 5;
readonly override size = 5;
}
@@ -0,0 +1,4 @@
{
"sourceType": "module",
"plugins": ["typescript", "classProperties"]
}
@@ -0,0 +1,11 @@
class MyClass extends BaseClass {
override show() {}

override public show() {}

override public show() {}

override size = 5;
override readonly size = 5;
override readonly size = 5;
}
2 changes: 2 additions & 0 deletions packages/babel-parser/src/parser/error-message.js
Expand Up @@ -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",
Expand Down
12 changes: 6 additions & 6 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -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();
Expand Down Expand Up @@ -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);
g-plane marked this conversation as resolved.
Show resolved Hide resolved
}
state.hadConstructor = true;
allowsDirectSuper = state.constructorAllowsSuper;
allowsDirectSuper = state.hadSuperClass;
}

this.pushClassMethod(
Expand Down
44 changes: 43 additions & 1 deletion packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -41,6 +41,7 @@ type TsModifier =
| "abstract"
| "declare"
| "static"
| "override"
| N.Accessibility;

function nonNull<T>(x: ?T): T {
Expand Down Expand Up @@ -85,12 +86,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:
Expand All @@ -106,6 +110,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:
Expand Down Expand Up @@ -256,6 +262,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;
}
Expand Down Expand Up @@ -621,7 +637,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,
);

Expand Down Expand Up @@ -2222,6 +2246,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
"private",
"public",
"protected",
"override",
]);

const callParseClassMember = () => {
Expand All @@ -2245,6 +2270,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
"readonly",
"declare",
"static",
"override",
]);

if (isStatic) {
Expand All @@ -2268,6 +2294,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;
}
Expand All @@ -2276,6 +2305,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);
Expand Down
4 changes: 3 additions & 1 deletion packages/babel-parser/src/types.js
Expand Up @@ -730,6 +730,7 @@ export type ClassMemberBase = NodeBase &
computed: boolean,
// TypeScript only:
accessibility?: ?Accessibility,
override?: ?true,
abstract?: ?true,
optional?: ?true,
};
Expand Down Expand Up @@ -807,6 +808,7 @@ export type ClassPrivateProperty = NodeBase & {
optional?: true,
definite?: true,
readonly?: true,
override?: true,
};

export type OptClassDeclaration = ClassBase &
Expand Down Expand Up @@ -1530,5 +1532,5 @@ export type ParseSubscriptState = {

export type ParseClassMemberState = {|
hadConstructor: boolean,
constructorAllowsSuper: boolean,
hadSuperClass: boolean,
|};
@@ -0,0 +1,15 @@
class MyClass2 extends BaseClass {
override constructor() {}
override [x: string]: any;
override static size = 5;
static override size = 5;
}

declare class MyClass3 extends BaseClass {
declare override prop1: any
override declare prop2: any
}

class MyClass4 {
override prop: any
}