Skip to content

Commit e453424

Browse files
committed
Refactor: integrate preanalysis result into analysis result
1 parent c22bb56 commit e453424

File tree

2 files changed

+34
-23
lines changed

2 files changed

+34
-23
lines changed

src/analysis.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import type { NodePath } from "@babel/core";
22
import type { Scope } from "@babel/traverse";
3-
import type { ClassDeclaration, ClassMethod, Identifier, JSXIdentifier } from "@babel/types";
3+
import type { ClassDeclaration, ClassMethod, Identifier, JSXIdentifier, TSType, TSTypeParameterDeclaration } from "@babel/types";
44
import { AnalysisError } from "./analysis/error.js";
55
import { analyzeThisFields } from "./analysis/this_fields.js";
66
import { analyzeState, StateObjAnalysis } from "./analysis/state.js";
77
import { getAndDelete } from "./utils.js";
88
import { analyzeProps, PropsObjAnalysis } from "./analysis/prop.js";
99
import { LocalManager, RemovableNode } from "./analysis/local.js";
1010
import { analyzeUserDefined, UserDefinedAnalysis } from "./analysis/user_defined.js";
11-
import { PreAnalysisResult } from "./analysis/pre.js";
11+
import type { PreAnalysisResult } from "./analysis/pre.js";
12+
import type { LibRef } from "./analysis/lib.js";
1213

1314
export { AnalysisError } from "./analysis/error.js";
1415

@@ -31,7 +32,12 @@ const SPECIAL_STATIC_NAMES = new Set<string>([
3132
]);
3233

3334
export type AnalysisResult = {
34-
locals: LocalManager,
35+
name?: Identifier | undefined;
36+
typeParameters?: NodePath<TSTypeParameterDeclaration> | undefined;
37+
superClassRef: LibRef;
38+
isPure: boolean;
39+
propsTyping: NodePath<TSType> | undefined;
40+
locals: LocalManager;
3541
render: RenderAnalysis;
3642
state: StateObjAnalysis;
3743
props: PropsObjAnalysis;
@@ -101,6 +107,11 @@ export function analyzeClass(
101107
}
102108

103109
return {
110+
name: preanalysis.name,
111+
typeParameters: preanalysis.typeParameters,
112+
superClassRef: preanalysis.superClassRef,
113+
isPure: preanalysis.isPure,
114+
propsTyping: preanalysis.props,
104115
locals,
105116
render,
106117
state: states,

src/index.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default function plugin(babel: typeof import("@babel/core")): PluginObj<P
2020
const declPath = path.parentPath;
2121
try {
2222
const analysis = analyzeClass(path, preanalysis);
23-
const { funcNode, typeNode } = transformClass(preanalysis, analysis, { ts }, babel);
23+
const { funcNode, typeNode } = transformClass(analysis, { ts }, babel);
2424
if (path.node.id) {
2525
// Necessary to avoid false error regarding duplicate declaration.
2626
path.scope.removeBinding(path.node.id.name);
@@ -48,7 +48,7 @@ export default function plugin(babel: typeof import("@babel/core")): PluginObj<P
4848
} else {
4949
try {
5050
const analysis = analyzeClass(path, preanalysis);
51-
const { funcNode, typeNode } = transformClass(preanalysis, analysis, { ts }, babel);
51+
const { funcNode, typeNode } = transformClass(analysis, { ts }, babel);
5252
// Necessary to avoid false error regarding duplicate declaration.
5353
path.scope.removeBinding(path.node.id.name);
5454
path.replaceWith(
@@ -77,7 +77,7 @@ type TransformResult = {
7777
typeNode?: TSType | undefined;
7878
};
7979

80-
function transformClass(preanalysis: PreAnalysisResult, analysis: AnalysisResult, options: { ts: boolean }, babel: typeof import("@babel/core")): TransformResult {
80+
function transformClass(analysis: AnalysisResult, options: { ts: boolean }, babel: typeof import("@babel/core")): TransformResult {
8181
const { types: t } = babel;
8282
const { ts } = options;
8383

@@ -207,7 +207,7 @@ function transformClass(preanalysis: PreAnalysisResult, analysis: AnalysisResult
207207
for (const field of analysis.state.values()) {
208208
// State declarations
209209
const call = t.callExpression(
210-
getReactImport("useState", babel, preanalysis.superClassRef),
210+
getReactImport("useState", babel, analysis.superClassRef),
211211
field.init ? [field.init.valuePath.node] : []
212212
);
213213
preamble.push(t.variableDeclaration("const", [
@@ -266,7 +266,7 @@ function transformClass(preanalysis: PreAnalysisResult, analysis: AnalysisResult
266266
} else if (field.type === "user_defined_ref") {
267267
// const foo = useRef(null);
268268
const call = t.callExpression(
269-
getReactImport("useRef", babel, preanalysis.superClassRef),
269+
getReactImport("useRef", babel, analysis.superClassRef),
270270
[t.nullLiteral()]
271271
);
272272
preamble.push(t.variableDeclaration(
@@ -286,7 +286,7 @@ function transformClass(preanalysis: PreAnalysisResult, analysis: AnalysisResult
286286
} else if (field.type === "user_defined_direct_ref") {
287287
// const foo = useRef(init);
288288
const call = t.callExpression(
289-
getReactImport("useRef", babel, preanalysis.superClassRef),
289+
getReactImport("useRef", babel, analysis.superClassRef),
290290
[field.init.node]
291291
);
292292
preamble.push(t.variableDeclaration(
@@ -309,26 +309,26 @@ function transformClass(preanalysis: PreAnalysisResult, analysis: AnalysisResult
309309
bodyNode.body.splice(0, 0, ...preamble);
310310
// recast is not smart enough to correctly pretty-print type parameters for arrow functions.
311311
// so we fall back to functions when type parameters are present.
312-
const functionNeeded = preanalysis.isPure || !!preanalysis.typeParameters;
312+
const functionNeeded = analysis.isPure || !!analysis.typeParameters;
313313
const params = needsProps(analysis)
314314
? [assignTypeAnnotation(
315315
t.identifier("props"),
316316
// If the function is generic, put type annotations here instead of the `const` to be defined.
317317
// TODO: take children into account, while being careful about difference between `@types/react` v17 and v18
318-
preanalysis.typeParameters
319-
? preanalysis.props
320-
? t.tsTypeAnnotation(preanalysis.props.node)
318+
analysis.typeParameters
319+
? analysis.propsTyping
320+
? t.tsTypeAnnotation(analysis.propsTyping.node)
321321
: undefined
322322
: undefined
323323
)]
324324
: [];
325325
// If the function is generic, put type annotations here instead of the `const` to be defined.
326-
const returnType = preanalysis.typeParameters
326+
const returnType = analysis.typeParameters
327327
// Construct `React.ReactElement | null`
328328
? t.tsTypeAnnotation(
329329
t.tsUnionType([
330330
t.tsTypeReference(
331-
toTSEntity(getReactImport("ReactElement", babel, preanalysis.superClassRef), babel)
331+
toTSEntity(getReactImport("ReactElement", babel, analysis.superClassRef), babel)
332332
),
333333
t.tsNullKeyword(),
334334
])
@@ -338,7 +338,7 @@ function transformClass(preanalysis: PreAnalysisResult, analysis: AnalysisResult
338338
assignReturnType(
339339
functionNeeded
340340
? t.functionExpression(
341-
preanalysis.name ? t.cloneNode(preanalysis.name) : undefined,
341+
analysis.name ? t.cloneNode(analysis.name) : undefined,
342342
params,
343343
bodyNode
344344
)
@@ -348,20 +348,20 @@ function transformClass(preanalysis: PreAnalysisResult, analysis: AnalysisResult
348348
),
349349
returnType
350350
),
351-
preanalysis.typeParameters?.node
351+
analysis.typeParameters?.node
352352
);
353353
return {
354-
funcNode: preanalysis.isPure
354+
funcNode: analysis.isPure
355355
? t.callExpression(
356-
getReactImport("memo", babel, preanalysis.superClassRef),
356+
getReactImport("memo", babel, analysis.superClassRef),
357357
[funcNode]
358358
)
359359
: funcNode,
360-
typeNode: ts && !preanalysis.typeParameters
360+
typeNode: ts && !analysis.typeParameters
361361
? t.tsTypeReference(
362-
toTSEntity(getReactImport("FC", babel, preanalysis.superClassRef), babel),
363-
preanalysis.props
364-
? t.tsTypeParameterInstantiation([preanalysis.props.node])
362+
toTSEntity(getReactImport("FC", babel, analysis.superClassRef), babel),
363+
analysis.propsTyping
364+
? t.tsTypeParameterInstantiation([analysis.propsTyping.node])
365365
: null
366366
)
367367
: undefined,

0 commit comments

Comments
 (0)