Add support for TS declare modifier on fields (#10545)
* [parser] Add support for TS declare modifier on fields (#10484) * [parser] Add support for TS declare modifier on fields * Use Object.create(null) * Comment * Add support for TS declare types to types and generator (#10544) * Transform TypeScript "declare" fields (#10546) * Transform TypeScript "declare" fields * Remove multiple spaces * declareFields -> allowDeclareFields * Update after rebase
This commit is contained in:
parent
87feda7c2a
commit
e9c1bce50f
@ -71,26 +71,8 @@ export function ClassBody(node: Object) {
|
|||||||
|
|
||||||
export function ClassProperty(node: Object) {
|
export function ClassProperty(node: Object) {
|
||||||
this.printJoin(node.decorators, node);
|
this.printJoin(node.decorators, node);
|
||||||
|
this.tsPrintClassMemberModifiers(node, /* isField */ true);
|
||||||
|
|
||||||
if (node.accessibility) {
|
|
||||||
// TS
|
|
||||||
this.word(node.accessibility);
|
|
||||||
this.space();
|
|
||||||
}
|
|
||||||
if (node.static) {
|
|
||||||
this.word("static");
|
|
||||||
this.space();
|
|
||||||
}
|
|
||||||
if (node.abstract) {
|
|
||||||
// TS
|
|
||||||
this.word("abstract");
|
|
||||||
this.space();
|
|
||||||
}
|
|
||||||
if (node.readonly) {
|
|
||||||
// TS
|
|
||||||
this.word("readonly");
|
|
||||||
this.space();
|
|
||||||
}
|
|
||||||
if (node.computed) {
|
if (node.computed) {
|
||||||
this.token("[");
|
this.token("[");
|
||||||
this.print(node.key, node);
|
this.print(node.key, node);
|
||||||
@ -148,23 +130,6 @@ export function ClassPrivateMethod(node: Object) {
|
|||||||
|
|
||||||
export function _classMethodHead(node) {
|
export function _classMethodHead(node) {
|
||||||
this.printJoin(node.decorators, node);
|
this.printJoin(node.decorators, node);
|
||||||
|
this.tsPrintClassMemberModifiers(node, /* isField */ false);
|
||||||
if (node.accessibility) {
|
|
||||||
// TS
|
|
||||||
this.word(node.accessibility);
|
|
||||||
this.space();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.abstract) {
|
|
||||||
// TS
|
|
||||||
this.word("abstract");
|
|
||||||
this.space();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.static) {
|
|
||||||
this.word("static");
|
|
||||||
this.space();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._methodHead(node);
|
this._methodHead(node);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -556,3 +556,26 @@ export function tsPrintSignatureDeclarationBase(node) {
|
|||||||
this.token(")");
|
this.token(")");
|
||||||
this.print(node.typeAnnotation, node);
|
this.print(node.typeAnnotation, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function tsPrintClassMemberModifiers(node, isField) {
|
||||||
|
if (isField && node.declare) {
|
||||||
|
this.word("declare");
|
||||||
|
this.space();
|
||||||
|
}
|
||||||
|
if (node.accessibility) {
|
||||||
|
this.word(node.accessibility);
|
||||||
|
this.space();
|
||||||
|
}
|
||||||
|
if (node.static) {
|
||||||
|
this.word("static");
|
||||||
|
this.space();
|
||||||
|
}
|
||||||
|
if (node.abstract) {
|
||||||
|
this.word("abstract");
|
||||||
|
this.space();
|
||||||
|
}
|
||||||
|
if (isField && node.readonly) {
|
||||||
|
this.word("readonly");
|
||||||
|
this.space();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
5
packages/babel-generator/test/fixtures/typescript/class-field-declare/input.js
vendored
Normal file
5
packages/babel-generator/test/fixtures/typescript/class-field-declare/input.js
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
class A {
|
||||||
|
declare foo;
|
||||||
|
declare bar: string;
|
||||||
|
declare readonly bax: number;
|
||||||
|
}
|
||||||
4
packages/babel-generator/test/fixtures/typescript/class-field-declare/options.json
vendored
Normal file
4
packages/babel-generator/test/fixtures/typescript/class-field-declare/options.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"sourceType": "module",
|
||||||
|
"plugins": ["typescript", "classProperties"]
|
||||||
|
}
|
||||||
5
packages/babel-generator/test/fixtures/typescript/class-field-declare/output.js
vendored
Normal file
5
packages/babel-generator/test/fixtures/typescript/class-field-declare/output.js
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
class A {
|
||||||
|
declare foo;
|
||||||
|
declare bar: string;
|
||||||
|
declare readonly bax: number;
|
||||||
|
}
|
||||||
@ -5,6 +5,8 @@ import ReplaceSupers, {
|
|||||||
import memberExpressionToFunctions from "@babel/helper-member-expression-to-functions";
|
import memberExpressionToFunctions from "@babel/helper-member-expression-to-functions";
|
||||||
import optimiseCall from "@babel/helper-optimise-call-expression";
|
import optimiseCall from "@babel/helper-optimise-call-expression";
|
||||||
|
|
||||||
|
import * as ts from "./typescript";
|
||||||
|
|
||||||
export function buildPrivateNamesMap(props) {
|
export function buildPrivateNamesMap(props) {
|
||||||
const privateNamesMap = new Map();
|
const privateNamesMap = new Map();
|
||||||
for (const prop of props) {
|
for (const prop of props) {
|
||||||
@ -556,6 +558,8 @@ export function buildFieldsInitNodes(
|
|||||||
let needsClassRef = false;
|
let needsClassRef = false;
|
||||||
|
|
||||||
for (const prop of props) {
|
for (const prop of props) {
|
||||||
|
ts.assertFieldTransformed(prop);
|
||||||
|
|
||||||
const isStatic = prop.node.static;
|
const isStatic = prop.node.static;
|
||||||
const isInstance = !isStatic;
|
const isInstance = !isStatic;
|
||||||
const isPrivate = prop.isPrivate();
|
const isPrivate = prop.isPrivate();
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
// @flow
|
||||||
|
|
||||||
|
import type { NodePath } from "@babel/traverse";
|
||||||
|
|
||||||
|
export function assertFieldTransformed(path: NodePath) {
|
||||||
|
// TODO (Babel 8): Also check path.node.definite
|
||||||
|
|
||||||
|
if (path.node.declare) {
|
||||||
|
throw path.buildCodeFrameError(
|
||||||
|
`TypeScript 'declare' fields must first be transformed by ` +
|
||||||
|
`@babel/plugin-transform-typescript.\n` +
|
||||||
|
`If you have already enabled that plugin (or '@babel/preset-typescript'), make sure ` +
|
||||||
|
`that it runs before any plugin related to additional class features:\n` +
|
||||||
|
` - @babel/plugin-proposal-class-properties\n` +
|
||||||
|
` - @babel/plugin-proposal-private-methods\n` +
|
||||||
|
` - @babel/plugin-proposal-decorators`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -28,6 +28,7 @@ import * as charCodes from "charcodes";
|
|||||||
type TsModifier =
|
type TsModifier =
|
||||||
| "readonly"
|
| "readonly"
|
||||||
| "abstract"
|
| "abstract"
|
||||||
|
| "declare"
|
||||||
| "static"
|
| "static"
|
||||||
| "public"
|
| "public"
|
||||||
| "private"
|
| "private"
|
||||||
@ -129,6 +130,31 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parses a list of modifiers, in any order.
|
||||||
|
* If you need a specific order, you must call this function multiple times:
|
||||||
|
* this.tsParseModifiers(["public"]);
|
||||||
|
* this.tsParseModifiers(["abstract", "readonly"]);
|
||||||
|
*/
|
||||||
|
tsParseModifiers<T: TsModifier>(
|
||||||
|
allowedModifiers: T[],
|
||||||
|
): { [key: TsModifier]: ?true, __proto__: null } {
|
||||||
|
const modifiers = Object.create(null);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const startPos = this.state.start;
|
||||||
|
const modifier: ?T = this.tsParseModifier(allowedModifiers);
|
||||||
|
|
||||||
|
if (!modifier) break;
|
||||||
|
|
||||||
|
if (Object.hasOwnProperty.call(modifiers, modifier)) {
|
||||||
|
this.raise(startPos, `Duplicate modifier: '${modifier}'`);
|
||||||
|
}
|
||||||
|
modifiers[modifier] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
tsIsListTerminator(kind: ParsingContext): boolean {
|
tsIsListTerminator(kind: ParsingContext): boolean {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case "EnumMembers":
|
case "EnumMembers":
|
||||||
@ -405,7 +431,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
return this.eat(tt.name) && this.match(tt.colon);
|
return this.eat(tt.name) && this.match(tt.colon);
|
||||||
}
|
}
|
||||||
|
|
||||||
tsTryParseIndexSignature(node: N.TsIndexSignature): ?N.TsIndexSignature {
|
tsTryParseIndexSignature(node: N.Node): ?N.TsIndexSignature {
|
||||||
if (
|
if (
|
||||||
!(
|
!(
|
||||||
this.match(tt.bracketL) &&
|
this.match(tt.bracketL) &&
|
||||||
@ -1844,50 +1870,49 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
parseClassMemberWithIsStatic(
|
parseClassMemberWithIsStatic(
|
||||||
classBody: N.ClassBody,
|
classBody: N.ClassBody,
|
||||||
member: any,
|
member: N.ClassMember | N.TsIndexSignature,
|
||||||
state: { hadConstructor: boolean },
|
state: { hadConstructor: boolean },
|
||||||
isStatic: boolean,
|
isStatic: boolean,
|
||||||
constructorAllowsSuper: boolean,
|
constructorAllowsSuper: boolean,
|
||||||
): void {
|
): void {
|
||||||
const methodOrProp: N.ClassMethod | N.ClassProperty = member;
|
const modifiers = this.tsParseModifiers([
|
||||||
const prop: N.ClassProperty = member;
|
"abstract",
|
||||||
const propOrIdx: N.ClassProperty | N.TsIndexSignature = member;
|
"readonly",
|
||||||
|
"declare",
|
||||||
|
]);
|
||||||
|
|
||||||
let abstract = false,
|
Object.assign(member, modifiers);
|
||||||
readonly = false;
|
|
||||||
|
|
||||||
const mod = this.tsParseModifier(["abstract", "readonly"]);
|
|
||||||
switch (mod) {
|
|
||||||
case "readonly":
|
|
||||||
readonly = true;
|
|
||||||
abstract = !!this.tsParseModifier(["abstract"]);
|
|
||||||
break;
|
|
||||||
case "abstract":
|
|
||||||
abstract = true;
|
|
||||||
readonly = !!this.tsParseModifier(["readonly"]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abstract) methodOrProp.abstract = true;
|
|
||||||
if (readonly) propOrIdx.readonly = true;
|
|
||||||
|
|
||||||
if (!abstract && !isStatic && !methodOrProp.accessibility) {
|
|
||||||
const idx = this.tsTryParseIndexSignature(member);
|
const idx = this.tsTryParseIndexSignature(member);
|
||||||
if (idx) {
|
if (idx) {
|
||||||
classBody.body.push(idx);
|
classBody.body.push(idx);
|
||||||
return;
|
|
||||||
|
if (modifiers.abstract) {
|
||||||
|
this.raise(
|
||||||
|
member.start,
|
||||||
|
"Index signatures cannot have the 'abstract' modifier",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
if (isStatic) {
|
||||||
|
this.raise(
|
||||||
|
member.start,
|
||||||
|
"Index signatures cannot have the 'static' modifier",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ((member: any).accessibility) {
|
||||||
|
this.raise(
|
||||||
|
member.start,
|
||||||
|
`Index signatures cannot have an accessibility modifier ('${
|
||||||
|
(member: any).accessibility
|
||||||
|
}')`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readonly) {
|
|
||||||
// Must be a property (if not an index signature).
|
|
||||||
methodOrProp.static = isStatic;
|
|
||||||
this.parseClassPropertyName(prop);
|
|
||||||
this.parsePostMemberNameModifiers(methodOrProp);
|
|
||||||
this.pushClassProperty(classBody, prop);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*:: invariant(member.type !== "TSIndexSignature") */
|
||||||
|
|
||||||
super.parseClassMemberWithIsStatic(
|
super.parseClassMemberWithIsStatic(
|
||||||
classBody,
|
classBody,
|
||||||
member,
|
member,
|
||||||
@ -1902,6 +1927,20 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
): void {
|
): void {
|
||||||
const optional = this.eat(tt.question);
|
const optional = this.eat(tt.question);
|
||||||
if (optional) methodOrProp.optional = true;
|
if (optional) methodOrProp.optional = true;
|
||||||
|
|
||||||
|
if ((methodOrProp: any).readonly && this.match(tt.parenL)) {
|
||||||
|
this.raise(
|
||||||
|
methodOrProp.start,
|
||||||
|
"Class methods cannot have the 'readonly' modifier",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((methodOrProp: any).declare && this.match(tt.parenL)) {
|
||||||
|
this.raise(
|
||||||
|
methodOrProp.start,
|
||||||
|
"Class methods cannot have the 'declare' modifier",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: The reason we do this in `parseExpressionStatement` and not `parseStatement`
|
// Note: The reason we do this in `parseExpressionStatement` and not `parseStatement`
|
||||||
@ -2048,6 +2087,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
parseClassProperty(node: N.ClassProperty): N.ClassProperty {
|
parseClassProperty(node: N.ClassProperty): N.ClassProperty {
|
||||||
this.parseClassPropertyAnnotation(node);
|
this.parseClassPropertyAnnotation(node);
|
||||||
|
|
||||||
|
if (node.declare && this.match(tt.equal)) {
|
||||||
|
this.raise(
|
||||||
|
this.state.start,
|
||||||
|
"'declare' class fields cannot have an initializer",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return super.parseClassProperty(node);
|
return super.parseClassProperty(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -743,7 +743,8 @@ export type ClassPrivateMethod = NodeBase &
|
|||||||
computed: false,
|
computed: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ClassProperty = ClassMemberBase & {
|
export type ClassProperty = ClassMemberBase &
|
||||||
|
DeclarationBase & {
|
||||||
type: "ClassProperty",
|
type: "ClassProperty",
|
||||||
key: Expression,
|
key: Expression,
|
||||||
value: ?Expression, // TODO: Not in spec that this is nullable.
|
value: ?Expression, // TODO: Not in spec that this is nullable.
|
||||||
|
|||||||
3
packages/babel-parser/test/fixtures/typescript/class/declare-field-initializer/input.ts
vendored
Normal file
3
packages/babel-parser/test/fixtures/typescript/class/declare-field-initializer/input.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
declare bar: string = "test";
|
||||||
|
}
|
||||||
170
packages/babel-parser/test/fixtures/typescript/class/declare-field-initializer/output.json
vendored
Normal file
170
packages/babel-parser/test/fixtures/typescript/class/declare-field-initializer/output.json
vendored
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start": 0,
|
||||||
|
"end": 43,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 0,
|
||||||
|
"end": 43,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceType": "module",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 43,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 6
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 7
|
||||||
|
},
|
||||||
|
"identifierName": "A"
|
||||||
|
},
|
||||||
|
"name": "A"
|
||||||
|
},
|
||||||
|
"superClass": null,
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start": 8,
|
||||||
|
"end": 43,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start": 12,
|
||||||
|
"end": 41,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 2
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 31
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"declare": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 20,
|
||||||
|
"end": 23,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 10
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"identifierName": "bar"
|
||||||
|
},
|
||||||
|
"name": "bar"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSTypeAnnotation",
|
||||||
|
"start": 23,
|
||||||
|
"end": 31,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 21
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSStringKeyword",
|
||||||
|
"start": 25,
|
||||||
|
"end": 31,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 15
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 21
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"type": "StringLiteral",
|
||||||
|
"start": 34,
|
||||||
|
"end": 40,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 24
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 30
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"rawValue": "test",
|
||||||
|
"raw": "\"test\""
|
||||||
|
},
|
||||||
|
"value": "test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
4
packages/babel-parser/test/fixtures/typescript/class/declare-field/input.ts
vendored
Normal file
4
packages/babel-parser/test/fixtures/typescript/class/declare-field/input.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
class A {
|
||||||
|
declare foo;
|
||||||
|
declare bar: string;
|
||||||
|
}
|
||||||
187
packages/babel-parser/test/fixtures/typescript/class/declare-field/output.json
vendored
Normal file
187
packages/babel-parser/test/fixtures/typescript/class/declare-field/output.json
vendored
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start": 0,
|
||||||
|
"end": 49,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 0,
|
||||||
|
"end": 49,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceType": "module",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 49,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 6
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 7
|
||||||
|
},
|
||||||
|
"identifierName": "A"
|
||||||
|
},
|
||||||
|
"name": "A"
|
||||||
|
},
|
||||||
|
"superClass": null,
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start": 8,
|
||||||
|
"end": 49,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start": 12,
|
||||||
|
"end": 24,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 2
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"declare": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 20,
|
||||||
|
"end": 23,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 10
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"identifierName": "foo"
|
||||||
|
},
|
||||||
|
"name": "foo"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ClassProperty",
|
||||||
|
"start": 27,
|
||||||
|
"end": 47,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 2
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 22
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"declare": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 35,
|
||||||
|
"end": 38,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 10
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"identifierName": "bar"
|
||||||
|
},
|
||||||
|
"name": "bar"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSTypeAnnotation",
|
||||||
|
"start": 38,
|
||||||
|
"end": 46,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 21
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSStringKeyword",
|
||||||
|
"start": 40,
|
||||||
|
"end": 46,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 15
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 21
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/babel-parser/test/fixtures/typescript/class/declare-method/input.ts
vendored
Normal file
3
packages/babel-parser/test/fixtures/typescript/class/declare-method/input.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
declare foo() {}
|
||||||
|
}
|
||||||
145
packages/babel-parser/test/fixtures/typescript/class/declare-method/output.json
vendored
Normal file
145
packages/babel-parser/test/fixtures/typescript/class/declare-method/output.json
vendored
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start": 0,
|
||||||
|
"end": 30,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errors": [
|
||||||
|
"SyntaxError: Class methods cannot have the 'declare' modifier (2:2)"
|
||||||
|
],
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 0,
|
||||||
|
"end": 30,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceType": "module",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 30,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 6
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 7
|
||||||
|
},
|
||||||
|
"identifierName": "A"
|
||||||
|
},
|
||||||
|
"name": "A"
|
||||||
|
},
|
||||||
|
"superClass": null,
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start": 8,
|
||||||
|
"end": 30,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start": 12,
|
||||||
|
"end": 28,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 2
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 18
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"declare": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 20,
|
||||||
|
"end": 23,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 10
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"identifierName": "foo"
|
||||||
|
},
|
||||||
|
"name": "foo"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "method",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start": 26,
|
||||||
|
"end": 28,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 16
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 18
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"throws": "Unexpected token, expected \";\" (2:14)"
|
|
||||||
}
|
|
||||||
145
packages/babel-parser/test/fixtures/typescript/class/method-readonly/output.json
vendored
Normal file
145
packages/babel-parser/test/fixtures/typescript/class/method-readonly/output.json
vendored
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start": 0,
|
||||||
|
"end": 31,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errors": [
|
||||||
|
"SyntaxError: Class methods cannot have the 'readonly' modifier (2:4)"
|
||||||
|
],
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start": 0,
|
||||||
|
"end": 31,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sourceType": "module",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassDeclaration",
|
||||||
|
"start": 0,
|
||||||
|
"end": 31,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 6,
|
||||||
|
"end": 7,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 6
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 7
|
||||||
|
},
|
||||||
|
"identifierName": "C"
|
||||||
|
},
|
||||||
|
"name": "C"
|
||||||
|
},
|
||||||
|
"superClass": null,
|
||||||
|
"body": {
|
||||||
|
"type": "ClassBody",
|
||||||
|
"start": 8,
|
||||||
|
"end": 31,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"column": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 3,
|
||||||
|
"column": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "ClassMethod",
|
||||||
|
"start": 14,
|
||||||
|
"end": 29,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 4
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 19
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readonly": true,
|
||||||
|
"static": false,
|
||||||
|
"key": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start": 23,
|
||||||
|
"end": 24,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 13
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 14
|
||||||
|
},
|
||||||
|
"identifierName": "m"
|
||||||
|
},
|
||||||
|
"name": "m"
|
||||||
|
},
|
||||||
|
"computed": false,
|
||||||
|
"kind": "method",
|
||||||
|
"id": null,
|
||||||
|
"generator": false,
|
||||||
|
"async": false,
|
||||||
|
"params": [],
|
||||||
|
"body": {
|
||||||
|
"type": "BlockStatement",
|
||||||
|
"start": 27,
|
||||||
|
"end": 29,
|
||||||
|
"loc": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 17
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"column": 19
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -77,7 +77,7 @@
|
|||||||
},
|
},
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"type": "ClassProperty",
|
"type": "ClassPrivateProperty",
|
||||||
"start": 12,
|
"start": 12,
|
||||||
"end": 24,
|
"end": 24,
|
||||||
"loc": {
|
"loc": {
|
||||||
@ -127,7 +127,7 @@
|
|||||||
"value": null
|
"value": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "ClassProperty",
|
"type": "ClassPrivateProperty",
|
||||||
"start": 27,
|
"start": 27,
|
||||||
"end": 47,
|
"end": 47,
|
||||||
"loc": {
|
"loc": {
|
||||||
|
|||||||
@ -44,11 +44,94 @@ function registerGlobalType(programScope, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default declare(
|
export default declare(
|
||||||
(api, { jsxPragma = "React", allowNamespaces = false }) => {
|
(
|
||||||
|
api,
|
||||||
|
{
|
||||||
|
jsxPragma = "React",
|
||||||
|
allowNamespaces = false,
|
||||||
|
allowDeclareFields = false,
|
||||||
|
},
|
||||||
|
) => {
|
||||||
api.assertVersion(7);
|
api.assertVersion(7);
|
||||||
|
|
||||||
const JSX_ANNOTATION_REGEX = /\*?\s*@jsx\s+([^\s]+)/;
|
const JSX_ANNOTATION_REGEX = /\*?\s*@jsx\s+([^\s]+)/;
|
||||||
|
|
||||||
|
const classMemberVisitors = {
|
||||||
|
field(path) {
|
||||||
|
const { node } = path;
|
||||||
|
|
||||||
|
if (!allowDeclareFields && node.declare) {
|
||||||
|
throw path.buildCodeFrameError(
|
||||||
|
`The 'declare' modifier is only allowed when the 'allowDeclareFields' option of ` +
|
||||||
|
`@babel/plugin-transform-typescript or @babel/preset-typescript is enabled.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (node.definite || node.declare) {
|
||||||
|
if (node.value) {
|
||||||
|
throw path.buildCodeFrameError(
|
||||||
|
`Definietly assigned fields and fields with the 'declare' modifier cannot` +
|
||||||
|
` be initialized here, but only in the constructor`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
path.remove();
|
||||||
|
} else if (!allowDeclareFields && !node.value && !node.decorators) {
|
||||||
|
path.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.accessibility) node.accessibility = null;
|
||||||
|
if (node.abstract) node.abstract = null;
|
||||||
|
if (node.readonly) node.readonly = null;
|
||||||
|
if (node.optional) node.optional = null;
|
||||||
|
if (node.typeAnnotation) node.typeAnnotation = null;
|
||||||
|
},
|
||||||
|
method({ node }) {
|
||||||
|
if (node.accessibility) node.accessibility = null;
|
||||||
|
if (node.abstract) node.abstract = null;
|
||||||
|
if (node.optional) node.optional = null;
|
||||||
|
|
||||||
|
// Rest handled by Function visitor
|
||||||
|
},
|
||||||
|
constructor(path, classPath) {
|
||||||
|
// Collects parameter properties so that we can add an assignment
|
||||||
|
// for each of them in the constructor body
|
||||||
|
//
|
||||||
|
// We use a WeakSet to ensure an assignment for a parameter
|
||||||
|
// property is only added once. This is necessary for cases like
|
||||||
|
// using `transform-classes`, which causes this visitor to run
|
||||||
|
// twice.
|
||||||
|
const parameterProperties = [];
|
||||||
|
for (const param of path.node.params) {
|
||||||
|
if (
|
||||||
|
param.type === "TSParameterProperty" &&
|
||||||
|
!PARSED_PARAMS.has(param.parameter)
|
||||||
|
) {
|
||||||
|
PARSED_PARAMS.add(param.parameter);
|
||||||
|
parameterProperties.push(param.parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameterProperties.length) {
|
||||||
|
const assigns = parameterProperties.map(p => {
|
||||||
|
let id;
|
||||||
|
if (t.isIdentifier(p)) {
|
||||||
|
id = p;
|
||||||
|
} else if (t.isAssignmentPattern(p) && t.isIdentifier(p.left)) {
|
||||||
|
id = p.left;
|
||||||
|
} else {
|
||||||
|
throw path.buildCodeFrameError(
|
||||||
|
"Parameter properties can not be destructuring patterns.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.statement.ast`this.${id} = ${id}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
injectInitialization(classPath, path, assigns);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: "transform-typescript",
|
name: "transform-typescript",
|
||||||
inherits: syntaxTypeScript,
|
inherits: syntaxTypeScript,
|
||||||
@ -192,27 +275,6 @@ export default declare(
|
|||||||
if (node.definite) node.definite = null;
|
if (node.definite) node.definite = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
ClassMethod(path) {
|
|
||||||
const { node } = path;
|
|
||||||
|
|
||||||
if (node.accessibility) node.accessibility = null;
|
|
||||||
if (node.abstract) node.abstract = null;
|
|
||||||
if (node.optional) node.optional = null;
|
|
||||||
|
|
||||||
// Rest handled by Function visitor
|
|
||||||
},
|
|
||||||
|
|
||||||
ClassProperty(path) {
|
|
||||||
const { node } = path;
|
|
||||||
|
|
||||||
if (node.accessibility) node.accessibility = null;
|
|
||||||
if (node.abstract) node.abstract = null;
|
|
||||||
if (node.readonly) node.readonly = null;
|
|
||||||
if (node.optional) node.optional = null;
|
|
||||||
if (node.definite) node.definite = null;
|
|
||||||
if (node.typeAnnotation) node.typeAnnotation = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
TSIndexSignature(path) {
|
TSIndexSignature(path) {
|
||||||
path.remove();
|
path.remove();
|
||||||
},
|
},
|
||||||
@ -238,54 +300,14 @@ export default declare(
|
|||||||
// class transform would transform the class, causing more specific
|
// class transform would transform the class, causing more specific
|
||||||
// visitors to not run.
|
// visitors to not run.
|
||||||
path.get("body.body").forEach(child => {
|
path.get("body.body").forEach(child => {
|
||||||
const childNode = child.node;
|
if (child.isClassMethod()) {
|
||||||
|
if (child.node.kind === "constructor") {
|
||||||
if (t.isClassMethod(childNode, { kind: "constructor" })) {
|
classMemberVisitors.constructor(child, path);
|
||||||
// Collects parameter properties so that we can add an assignment
|
|
||||||
// for each of them in the constructor body
|
|
||||||
//
|
|
||||||
// We use a WeakSet to ensure an assignment for a parameter
|
|
||||||
// property is only added once. This is necessary for cases like
|
|
||||||
// using `transform-classes`, which causes this visitor to run
|
|
||||||
// twice.
|
|
||||||
const parameterProperties = [];
|
|
||||||
for (const param of childNode.params) {
|
|
||||||
if (
|
|
||||||
param.type === "TSParameterProperty" &&
|
|
||||||
!PARSED_PARAMS.has(param.parameter)
|
|
||||||
) {
|
|
||||||
PARSED_PARAMS.add(param.parameter);
|
|
||||||
parameterProperties.push(param.parameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameterProperties.length) {
|
|
||||||
const assigns = parameterProperties.map(p => {
|
|
||||||
let id;
|
|
||||||
if (t.isIdentifier(p)) {
|
|
||||||
id = p;
|
|
||||||
} else if (
|
|
||||||
t.isAssignmentPattern(p) &&
|
|
||||||
t.isIdentifier(p.left)
|
|
||||||
) {
|
|
||||||
id = p.left;
|
|
||||||
} else {
|
} else {
|
||||||
throw path.buildCodeFrameError(
|
classMemberVisitors.method(child, path);
|
||||||
"Parameter properties can not be destructuring patterns.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return template.statement.ast`this.${id} = ${id}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
injectInitialization(path, child, assigns);
|
|
||||||
}
|
}
|
||||||
} else if (child.isClassProperty()) {
|
} else if (child.isClassProperty()) {
|
||||||
childNode.typeAnnotation = null;
|
classMemberVisitors.field(child, path);
|
||||||
|
|
||||||
if (!childNode.value && !childNode.decorators) {
|
|
||||||
child.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
3
packages/babel-plugin-transform-typescript/test/fixtures/class/declare-not-enabled/input.ts
vendored
Normal file
3
packages/babel-plugin-transform-typescript/test/fixtures/class/declare-not-enabled/input.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
declare x;
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["transform-typescript"],
|
||||||
|
"throws": "The 'declare' modifier is only allowed when the 'allowDeclareFields' option of @babel/plugin-transform-typescript or @babel/preset-typescript is enabled."
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
x;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": [["transform-typescript", { "allowDeclareFields": true }]]
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
x;
|
||||||
|
}
|
||||||
3
packages/babel-plugin-transform-typescript/test/fixtures/class/declare/input.ts
vendored
Normal file
3
packages/babel-plugin-transform-typescript/test/fixtures/class/declare/input.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
declare x;
|
||||||
|
}
|
||||||
3
packages/babel-plugin-transform-typescript/test/fixtures/class/declare/options.json
vendored
Normal file
3
packages/babel-plugin-transform-typescript/test/fixtures/class/declare/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": [["transform-typescript", { "allowDeclareFields": true }]]
|
||||||
|
}
|
||||||
1
packages/babel-plugin-transform-typescript/test/fixtures/class/declare/output.js
vendored
Normal file
1
packages/babel-plugin-transform-typescript/test/fixtures/class/declare/output.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
class A {}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
class C {
|
class C {
|
||||||
public a?: number;
|
public a?: number;
|
||||||
private b: number = 0;
|
private b: number = 0;
|
||||||
readonly c!: number = 1;
|
readonly c: number = 1;
|
||||||
@foo d: number;
|
@foo d: number;
|
||||||
@foo e: number = 3;
|
@foo e: number = 3;
|
||||||
|
f!: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
class A {
|
||||||
|
declare x;
|
||||||
|
y;
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"proposal-class-properties",
|
||||||
|
["transform-typescript", { "allowDeclareFields": true }]
|
||||||
|
],
|
||||||
|
"throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript.\nIf you have already enabled that plugin (or '@babel/preset-typescript'), make sure that it runs before any plugin related to additional class features:\n - @babel/plugin-proposal-class-properties\n - @babel/plugin-proposal-private-methods\n - @babel/plugin-proposal-decorators"
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
class A {
|
||||||
|
declare x;
|
||||||
|
y;
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["transform-typescript", { "allowDeclareFields": true }],
|
||||||
|
"proposal-class-properties"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||||
|
|
||||||
|
class A {
|
||||||
|
constructor() {
|
||||||
|
_defineProperty(this, "y", void 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
class A {
|
||||||
|
x!;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": [["transform-typescript", { "allowDeclareFields": true }]]
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
class A {}
|
||||||
@ -4,7 +4,13 @@ import transformTypeScript from "@babel/plugin-transform-typescript";
|
|||||||
export default declare(
|
export default declare(
|
||||||
(
|
(
|
||||||
api,
|
api,
|
||||||
{ jsxPragma, allExtensions = false, isTSX = false, allowNamespaces },
|
{
|
||||||
|
jsxPragma,
|
||||||
|
allExtensions = false,
|
||||||
|
isTSX = false,
|
||||||
|
allowNamespaces,
|
||||||
|
allowDeclareFields,
|
||||||
|
},
|
||||||
) => {
|
) => {
|
||||||
api.assertVersion(7);
|
api.assertVersion(7);
|
||||||
|
|
||||||
@ -19,13 +25,18 @@ export default declare(
|
|||||||
throw new Error("isTSX:true requires allExtensions:true");
|
throw new Error("isTSX:true requires allExtensions:true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pluginOptions = isTSX => ({
|
||||||
|
jsxPragma,
|
||||||
|
isTSX,
|
||||||
|
allowNamespaces,
|
||||||
|
allowDeclareFields,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
overrides: allExtensions
|
overrides: allExtensions
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
plugins: [
|
plugins: [[transformTypeScript, pluginOptions(isTSX)]],
|
||||||
[transformTypeScript, { jsxPragma, isTSX, allowNamespaces }],
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
@ -33,18 +44,13 @@ export default declare(
|
|||||||
// Only set 'test' if explicitly requested, since it requires that
|
// Only set 'test' if explicitly requested, since it requires that
|
||||||
// Babel is being called`
|
// Babel is being called`
|
||||||
test: /\.ts$/,
|
test: /\.ts$/,
|
||||||
plugins: [[transformTypeScript, { jsxPragma, allowNamespaces }]],
|
plugins: [[transformTypeScript, pluginOptions(false)]],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Only set 'test' if explicitly requested, since it requires that
|
// Only set 'test' if explicitly requested, since it requires that
|
||||||
// Babel is being called`
|
// Babel is being called`
|
||||||
test: /\.tsx$/,
|
test: /\.tsx$/,
|
||||||
plugins: [
|
plugins: [[transformTypeScript, pluginOptions(true)]],
|
||||||
[
|
|
||||||
transformTypeScript,
|
|
||||||
{ jsxPragma, isTSX: true, allowNamespaces },
|
|
||||||
],
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -67,6 +67,10 @@ defineType("ClassProperty", {
|
|||||||
validate: assertValueType("boolean"),
|
validate: assertValueType("boolean"),
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
declare: {
|
||||||
|
validate: assertValueType("boolean"),
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user