Skip to content

Commit

Permalink
Don't transform declare class in proposal-class-properties (#13854)
Browse files Browse the repository at this point in the history
Co-authored-by: Nicol貌 Ribaudo <nicolo.ribaudo@gmail.com>
  • Loading branch information
forivall and nicolo-ribaudo committed Oct 20, 2021
1 parent 29f697c commit fca5c9a
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 18 deletions.
2 changes: 1 addition & 1 deletion packages/babel-core/src/config/full.ts
Expand Up @@ -92,7 +92,7 @@ export default gensync<(inputOpts: unknown) => ResolvedConfig | null>(
function* recursePresetDescriptors(
rawPresets: Array<UnloadedDescriptor>,
pluginDescriptorsPass: Array<UnloadedDescriptor>,
) {
): Handler<true | void> {
const presets: Array<{
preset: ConfigChain | null;
pass: Array<UnloadedDescriptor>;
Expand Down
Expand Up @@ -18,6 +18,7 @@ import {
FEATURES,
isLoose,
} from "./features";
import { assertFieldTransformed } from "./typescript";

export { FEATURES, enableFeature, injectInitialization };

Expand Down Expand Up @@ -98,6 +99,8 @@ export function createClassFeaturePlugin({

verifyUsedFeatures(path, this.file);

if (path.isClassDeclaration()) assertFieldTransformed(path);

const loose = isLoose(this.file, feature);

let constructor: NodePath<t.ClassMethod>;
Expand Down
@@ -1,7 +1,9 @@
import type { NodePath } from "@babel/traverse";
import type * as t from "@babel/types";

export function assertFieldTransformed(path: NodePath<t.ClassProperty>) {
export function assertFieldTransformed(
path: NodePath<t.ClassProperty | t.ClassDeclaration>,
) {
// TODO (Babel 8): Also check path.node.definite

if (path.node.declare) {
Expand Down
@@ -0,0 +1,3 @@
declare class Foo {
static bar: string;
}
@@ -0,0 +1,5 @@
{
"presets": ["typescript"],
"plugins": ["proposal-class-properties"],
"throws": "TypeScript 'declare' fields must first be transformed by @babel/plugin-transform-typescript."
}
3 changes: 2 additions & 1 deletion packages/babel-plugin-transform-typescript/src/const-enum.ts
Expand Up @@ -3,8 +3,9 @@ import type { NodePath } from "@babel/traverse";

import { translateEnumValues } from "./enum";

export type NodePathConstEnum = NodePath<t.TSEnumDeclaration & { const: true }>;
export default function transpileConstEnum(
path: NodePath<t.TSEnumDeclaration & { const: true }>,
path: NodePathConstEnum,
t: typeof import("@babel/types"),
) {
const { name } = path.node.id;
Expand Down
70 changes: 55 additions & 15 deletions packages/babel-plugin-transform-typescript/src/index.ts
@@ -1,22 +1,27 @@
import { declare } from "@babel/helper-plugin-utils";
import syntaxTypeScript from "@babel/plugin-syntax-typescript";
import { types as t, template } from "@babel/core";
import type { PluginPass } from "@babel/core";
import { injectInitialization } from "@babel/helper-create-class-features-plugin";
import type { NodePath, Visitor } from "@babel/traverse";

import transpileConstEnum from "./const-enum";
import type { NodePathConstEnum } from "./const-enum";
import transpileEnum from "./enum";
import transpileNamespace from "./namespace";
import type { NodePath } from "@babel/traverse";

function isInType(path) {
function isInType(path: NodePath) {
switch (path.parent.type) {
case "TSTypeReference":
case "TSQualifiedName":
case "TSExpressionWithTypeArguments":
case "TSTypeQuery":
return true;
case "ExportSpecifier":
return path.parentPath.parent.exportKind === "type";
return (
(path.parentPath.parent as t.ExportNamedDeclaration).exportKind ===
"type"
);
default:
return false;
}
Expand All @@ -29,7 +34,7 @@ const GLOBAL_TYPES = new WeakMap();
const NEEDS_EXPLICIT_ESM = new WeakMap();
const PARSED_PARAMS = new WeakSet();

function isGlobalType(path, name) {
function isGlobalType(path: NodePath, name: string) {
const program = path.find(path => path.isProgram()).node;
if (path.scope.hasOwnBinding(name)) return false;
if (GLOBAL_TYPES.get(program).has(name)) return true;
Expand All @@ -47,11 +52,34 @@ function isGlobalType(path, name) {
return false;
}

function registerGlobalType(programNode, name) {
function registerGlobalType(programNode: t.Program, name: string) {
GLOBAL_TYPES.get(programNode).add(name);
}

export default declare((api, opts) => {
export interface Options {
/** @default true */
allowNamespaces?: boolean;
/** @default "React.createElement" */
jsxPragma?: string;
/** @default "React.Fragment" */
jsxPragmaFrag?: string;
onlyRemoveTypeImports?: boolean;
optimizeConstEnums?: boolean;
allowDeclareFields?: boolean;
}
type ConfigAPI = { assertVersion: (range: string | number) => void };
interface Plugin {
name: string;
visitor: Visitor<PluginPass>;
inherits: typeof syntaxTypeScript;
}
type ExtraNodeProps = {
declare?: unknown;
accessibility?: unknown;
abstract?: unknown;
optional?: unknown;
override?: unknown;
};
export default declare((api: ConfigAPI, opts: Options): Plugin => {
api.assertVersion(7);

const JSX_PRAGMA_REGEX = /\*?\s*@jsx((?:Frag)?)\s+([^\s]+)/;
Expand All @@ -70,7 +98,11 @@ export default declare((api, opts) => {
}

const classMemberVisitors = {
field(path) {
field(
path: NodePath<
(t.ClassPrivateProperty | t.ClassProperty) & ExtraNodeProps
>,
) {
const { node } = path;

if (!process.env.BABEL_8_BREAKING) {
Expand Down Expand Up @@ -302,7 +334,11 @@ export default declare((api, opts) => {
(stmt.isTSModuleDeclaration({ declare: true }) &&
stmt.get("id").isIdentifier())
) {
registerGlobalType(programNode, stmt.node.id.name);
registerGlobalType(
programNode,
//@ts-expect-error
stmt.node.id.name,
);
}
}
},
Expand Down Expand Up @@ -339,8 +375,10 @@ export default declare((api, opts) => {
if (
!path.node.source &&
path.node.specifiers.length > 0 &&
path.node.specifiers.every(({ local }) =>
isGlobalType(path, local.name),
path.node.specifiers.every(
specifier =>
t.isExportSpecifier(specifier) &&
isGlobalType(path, specifier.local.name),
)
) {
path.remove();
Expand All @@ -352,7 +390,9 @@ export default declare((api, opts) => {

ExportSpecifier(path) {
// remove type exports
if (!path.parent.source && isGlobalType(path, path.node.local.name)) {
type Parent = t.ExportDeclaration & { source?: t.StringLiteral };
const parent = path.parent as Parent;
if (!parent.source && isGlobalType(path, path.node.local.name)) {
path.remove();
}
},
Expand Down Expand Up @@ -406,7 +446,7 @@ export default declare((api, opts) => {
},

Class(path) {
const { node } = path;
const { node }: { node: typeof path.node & ExtraNodeProps } = path;

if (node.typeParameters) node.typeParameters = null;
if (node.superTypeParameters) node.superTypeParameters = null;
Expand Down Expand Up @@ -469,7 +509,7 @@ export default declare((api, opts) => {

TSEnumDeclaration(path) {
if (optimizeConstEnums && path.node.const) {
transpileConstEnum(path, t);
transpileConstEnum(path as NodePathConstEnum, t);
} else {
transpileEnum(path, t);
}
Expand Down Expand Up @@ -510,7 +550,7 @@ export default declare((api, opts) => {
},

TSAsExpression(path) {
let { node } = path;
let { node }: { node: t.Expression } = path;
do {
node = node.expression;
} while (t.isTSAsExpression(node));
Expand Down

0 comments on commit fca5c9a

Please sign in to comment.