Add the decoratorsAutoAccessors parser plugin (#13681)

Co-authored-by: Huáng Jùnliàng <jlhwung@gmail.com>
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
Chris Garrett
2021-10-04 11:08:14 -04:00
committed by Nicolò Ribaudo
parent dc5f419fa9
commit 3f3ce5f668
50 changed files with 1095 additions and 5 deletions

View File

@@ -506,6 +506,12 @@ export function assertClassProperty(
): asserts node is t.ClassProperty {
assert("ClassProperty", node, opts);
}
export function assertClassAccessorProperty(
node: object | null | undefined,
opts?: object | null,
): asserts node is t.ClassAccessorProperty {
assert("ClassAccessorProperty", node, opts);
}
export function assertClassPrivateProperty(
node: object | null | undefined,
opts?: object | null,
@@ -1694,6 +1700,12 @@ export function assertModuleSpecifier(
): asserts node is t.ModuleSpecifier {
assert("ModuleSpecifier", node, opts);
}
export function assertAccessor(
node: object | null | undefined,
opts?: object | null,
): asserts node is t.Accessor {
assert("Accessor", node, opts);
}
export function assertPrivate(
node: object | null | undefined,
opts?: object | null,

View File

@@ -65,6 +65,7 @@ export type Node =
| BreakStatement
| CallExpression
| CatchClause
| ClassAccessorProperty
| ClassBody
| ClassDeclaration
| ClassExpression
@@ -988,6 +989,24 @@ export interface ClassProperty extends BaseNode {
variance?: Variance | null;
}
export interface ClassAccessorProperty extends BaseNode {
type: "ClassAccessorProperty";
key: Identifier | StringLiteral | NumericLiteral | Expression | PrivateName;
value?: Expression | null;
typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null;
decorators?: Array<Decorator> | null;
computed?: boolean;
static?: boolean;
abstract?: boolean | null;
accessibility?: "public" | "private" | "protected" | null;
declare?: boolean | null;
definite?: boolean | null;
optional?: boolean | null;
override?: boolean;
readonly?: boolean | null;
variance?: Variance | null;
}
export interface ClassPrivateProperty extends BaseNode {
type: "ClassPrivateProperty";
key: PrivateName;
@@ -2094,6 +2113,7 @@ export type Standardized =
| OptionalMemberExpression
| OptionalCallExpression
| ClassProperty
| ClassAccessorProperty
| ClassPrivateProperty
| ClassPrivateMethod
| PrivateName
@@ -2366,7 +2386,11 @@ export type UserWhitespacable =
| ObjectTypeSpreadProperty;
export type Method = ObjectMethod | ClassMethod | ClassPrivateMethod;
export type ObjectMember = ObjectMethod | ObjectProperty;
export type Property = ObjectProperty | ClassProperty | ClassPrivateProperty;
export type Property =
| ObjectProperty
| ClassProperty
| ClassAccessorProperty
| ClassPrivateProperty;
export type UnaryLike = UnaryExpression | SpreadElement;
export type Pattern = AssignmentPattern | ArrayPattern | ObjectPattern;
export type Class = ClassExpression | ClassDeclaration;
@@ -2386,6 +2410,7 @@ export type ModuleSpecifier =
| ImportSpecifier
| ExportNamespaceSpecifier
| ExportDefaultSpecifier;
export type Accessor = ClassAccessorProperty;
export type Private = ClassPrivateProperty | ClassPrivateMethod | PrivateName;
export type Flow =
| AnyTypeAnnotation
@@ -2691,6 +2716,7 @@ export interface Aliases {
ModuleDeclaration: ModuleDeclaration;
ExportDeclaration: ExportDeclaration;
ModuleSpecifier: ModuleSpecifier;
Accessor: Accessor;
Private: Private;
Flow: Flow;
FlowType: FlowType;

View File

@@ -525,6 +525,21 @@ export function classProperty(
): t.ClassProperty {
return builder.apply("ClassProperty", arguments);
}
export function classAccessorProperty(
key:
| t.Identifier
| t.StringLiteral
| t.NumericLiteral
| t.Expression
| t.PrivateName,
value?: t.Expression | null,
typeAnnotation?: t.TypeAnnotation | t.TSTypeAnnotation | t.Noop | null,
decorators?: Array<t.Decorator> | null,
computed?: boolean,
_static?: boolean,
): t.ClassAccessorProperty {
return builder.apply("ClassAccessorProperty", arguments);
}
export function classPrivateProperty(
key: t.PrivateName,
value: t.Expression | null | undefined,

View File

@@ -91,6 +91,7 @@ export {
optionalMemberExpression as OptionalMemberExpression,
optionalCallExpression as OptionalCallExpression,
classProperty as ClassProperty,
classAccessorProperty as ClassAccessorProperty,
classPrivateProperty as ClassPrivateProperty,
classPrivateMethod as ClassPrivateMethod,
privateName as PrivateName,

View File

@@ -39,6 +39,7 @@ export const CLASS_TYPES = FLIPPED_ALIAS_KEYS["Class"];
export const MODULEDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["ModuleDeclaration"];
export const EXPORTDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["ExportDeclaration"];
export const MODULESPECIFIER_TYPES = FLIPPED_ALIAS_KEYS["ModuleSpecifier"];
export const ACCESSOR_TYPES = FLIPPED_ALIAS_KEYS["Accessor"];
export const PRIVATE_TYPES = FLIPPED_ALIAS_KEYS["Private"];
export const FLOW_TYPES = FLIPPED_ALIAS_KEYS["Flow"];
export const FLOWTYPE_TYPES = FLIPPED_ALIAS_KEYS["FlowType"];

View File

@@ -8,6 +8,7 @@ export default function toComputedKey(
| t.ObjectProperty
| t.ClassMethod
| t.ClassProperty
| t.ClassAccessorProperty
| t.MemberExpression
| t.OptionalMemberExpression,
// @ts-expect-error todo(flow->ts): maybe check the type of node before accessing .key and .property

View File

@@ -2126,6 +2126,80 @@ defineType("ClassProperty", {
},
});
defineType("ClassAccessorProperty", {
visitor: ["key", "value", "typeAnnotation", "decorators"],
builder: [
"key",
"value",
"typeAnnotation",
"decorators",
"computed",
"static",
],
aliases: ["Property", "Accessor"],
fields: {
...classMethodOrPropertyCommon,
key: {
validate: chain(
(function () {
const normal = assertNodeType(
"Identifier",
"StringLiteral",
"NumericLiteral",
"PrivateName",
);
const computed = assertNodeType("Expression");
return function (node: any, key: string, val: any) {
const validator = node.computed ? computed : normal;
validator(node, key, val);
};
})(),
assertNodeType(
"Identifier",
"StringLiteral",
"NumericLiteral",
"Expression",
"PrivateName",
),
),
},
value: {
validate: assertNodeType("Expression"),
optional: true,
},
definite: {
validate: assertValueType("boolean"),
optional: true,
},
typeAnnotation: {
validate: process.env.BABEL_8_BREAKING
? assertNodeType("TypeAnnotation", "TSTypeAnnotation")
: assertNodeType("TypeAnnotation", "TSTypeAnnotation", "Noop"),
optional: true,
},
decorators: {
validate: chain(
assertValueType("array"),
assertEach(assertNodeType("Decorator")),
),
optional: true,
},
readonly: {
validate: assertValueType("boolean"),
optional: true,
},
declare: {
validate: assertValueType("boolean"),
optional: true,
},
variance: {
validate: assertNodeType("Variance"),
optional: true,
},
},
});
defineType("ClassPrivateProperty", {
visitor: ["key", "value", "decorators", "typeAnnotation"],
builder: ["key", "value", "decorators", "static"],

View File

@@ -1399,6 +1399,23 @@ export function isClassProperty(
return false;
}
export function isClassAccessorProperty(
node: object | null | undefined,
opts?: object | null,
): node is t.ClassAccessorProperty {
if (!node) return false;
const nodeType = (node as t.Node).type;
if (nodeType === "ClassAccessorProperty") {
if (typeof opts === "undefined") {
return true;
} else {
return shallowEqual(node, opts);
}
}
return false;
}
export function isClassPrivateProperty(
node: object | null | undefined,
opts?: object | null,
@@ -4277,6 +4294,7 @@ export function isStandardized(
"OptionalMemberExpression" === nodeType ||
"OptionalCallExpression" === nodeType ||
"ClassProperty" === nodeType ||
"ClassAccessorProperty" === nodeType ||
"ClassPrivateProperty" === nodeType ||
"ClassPrivateMethod" === nodeType ||
"PrivateName" === nodeType ||
@@ -5052,6 +5070,7 @@ export function isProperty(
if (
"ObjectProperty" === nodeType ||
"ClassProperty" === nodeType ||
"ClassAccessorProperty" === nodeType ||
"ClassPrivateProperty" === nodeType
) {
if (typeof opts === "undefined") {
@@ -5187,6 +5206,23 @@ export function isModuleSpecifier(
return false;
}
export function isAccessor(
node: object | null | undefined,
opts?: object | null,
): node is t.Accessor {
if (!node) return false;
const nodeType = (node as t.Node).type;
if ("ClassAccessorProperty" === nodeType) {
if (typeof opts === "undefined") {
return true;
} else {
return shallowEqual(node, opts);
}
}
return false;
}
export function isPrivate(
node: object | null | undefined,
opts?: object | null,

View File

@@ -63,6 +63,7 @@ export default function isReferenced(
// yes: class { [NODE] = value; }
// yes: class { key = NODE; }
case "ClassProperty":
case "ClassAccessorProperty":
if (parent.key === node) {
return !!parent.computed;
}