fix(props): rename the prop without alias and deconstruction

This commit is contained in:
Hoikan 2024-05-24 17:56:42 +08:00
parent c7de85630e
commit b15d746697
3 changed files with 36 additions and 20 deletions

View File

@ -23,5 +23,5 @@ graph TD
see `types.ts` in `packages/transpiler/babel-inula-next-core/src/analyze/types.ts` see `types.ts` in `packages/transpiler/babel-inula-next-core/src/analyze/types.ts`
## TODO LIST ## TODO LIST
- [ ] for analyze the local variable, we need to consider the scope of the variable - [x] for analyze the local variable, we need to consider the scope of the variable
- [ ] hook analyze - [ ] hook analyze

View File

@ -4,6 +4,7 @@ import { register } from '@openinula/babel-api';
import { COMPONENT } from '../constants'; import { COMPONENT } from '../constants';
import { ArrowFunctionWithBlock, extractFnFromMacro, isCompPath, wrapArrowFunctionWithBlock } from '../utils'; import { ArrowFunctionWithBlock, extractFnFromMacro, isCompPath, wrapArrowFunctionWithBlock } from '../utils';
import { types as t } from '@openinula/babel-api'; import { types as t } from '@openinula/babel-api';
import { type Scope } from '@babel/traverse';
export enum PropType { export enum PropType {
REST = 'rest', REST = 'rest',
@ -27,10 +28,9 @@ interface Prop {
// let p20 // let p20
// let p21 // let p21
// } // }
function createPropAssignment(prop: Prop) { function createPropAssignment(prop: Prop, scope: Scope) {
const decalrations = [ const newName = `${prop.name}_$$prop`;
t.variableDeclaration('let', [t.variableDeclarator(t.identifier(`${prop.name}_$$prop`), prop.defaultVal)]), const decalrations = [t.variableDeclaration('let', [t.variableDeclarator(t.identifier(newName), prop.defaultVal)])];
];
if (prop.alias) { if (prop.alias) {
decalrations.push( decalrations.push(
t.variableDeclaration('let', [ t.variableDeclaration('let', [
@ -44,10 +44,22 @@ function createPropAssignment(prop: Prop) {
); );
} }
if (!prop.nestedRelationship || !prop.alias) {
// this means the prop can be used directly in the function body
// need rename the prop
scope.rename(prop.name, newName);
}
return decalrations; return decalrations;
} }
function extractPropsDestructing( /**
* Find the props destructuring in the function body, like:
* const { prop1, prop2 } = props;
* To extract the props
* @param fnPath
* @param propsName
*/
function extractPropsDestructingInFnBody(
fnPath: NodePath<t.FunctionExpression> | NodePath<ArrowFunctionWithBlock>, fnPath: NodePath<t.FunctionExpression> | NodePath<ArrowFunctionWithBlock>,
propsName: string propsName: string
) { ) {
@ -62,9 +74,9 @@ function extractPropsDestructing(
const id = declaration.get('id'); const id = declaration.get('id');
if (init.isIdentifier() && init.node.name === propsName) { if (init.isIdentifier() && init.node.name === propsName) {
if (id.isObjectPattern()) { if (id.isObjectPattern()) {
props = id.get('properties').map(prop => parseSingleProp(prop)); props = id.get('properties').map(prop => parseProperty(prop));
} else if (id.isIdentifier()) { } else if (id.isIdentifier()) {
props = extractPropsDestructing(fnPath, id.node.name); props = extractPropsDestructingInFnBody(fnPath, id.node.name);
} }
// delete the declaration // delete the declaration
if (props.length > 0) { if (props.length > 0) {
@ -113,13 +125,14 @@ export default function (api: typeof babel, options: DLightOption): PluginObj {
if (propsPath) { if (propsPath) {
if (propsPath.isObjectPattern()) { if (propsPath.isObjectPattern()) {
// --- object destructuring --- // --- object destructuring ---
props = propsPath.get('properties').map(prop => parseSingleProp(prop)); props = propsPath.get('properties').map(prop => parseProperty(prop));
} else if (propsPath.isIdentifier()) { } else if (propsPath.isIdentifier()) {
props = extractPropsDestructing(fnPath, propsPath.node.name); // --- identifier destructuring ---
props = extractPropsDestructingInFnBody(fnPath, propsPath.node.name);
} }
} }
fnPath.node.body.body.unshift(...props.flatMap(prop => createPropAssignment(prop))); fnPath.node.body.body.unshift(...props.flatMap(prop => createPropAssignment(prop, fnPath.scope)));
// --- clear the props --- // --- clear the props ---
fnPath.node.params = []; fnPath.node.params = [];
@ -129,14 +142,14 @@ export default function (api: typeof babel, options: DLightOption): PluginObj {
}; };
} }
function parseSingleProp(path: NodePath<t.ObjectProperty | t.RestElement>): Prop { function parseProperty(path: NodePath<t.ObjectProperty | t.RestElement>): Prop {
if (path.isObjectProperty()) { if (path.isObjectProperty()) {
// --- normal property --- // --- normal property ---
const key = path.node.key; const key = path.node.key;
const value = path.node.value; const value = path.node.value;
if (t.isIdentifier(key) || t.isStringLiteral(key)) { if (t.isIdentifier(key) || t.isStringLiteral(key)) {
const name = t.isIdentifier(key) ? key.name : key.value; const name = t.isIdentifier(key) ? key.name : key.value;
return analyzeNestedProp(value, name, path); return analyzeNestedProp(value, name);
} }
throw Error(`Unsupported key type in object destructuring: ${key.type}`); throw Error(`Unsupported key type in object destructuring: ${key.type}`);
@ -153,7 +166,7 @@ function parseSingleProp(path: NodePath<t.ObjectProperty | t.RestElement>): Prop
} }
} }
function analyzeNestedProp(value: t.ObjectProperty['value'], name: string, path: NodePath<t.ObjectProperty>): Prop { function analyzeNestedProp(value: t.ObjectProperty['value'], name: string): Prop {
let defaultVal: t.Expression | null = null; let defaultVal: t.Expression | null = null;
let alias: string | null = null; let alias: string | null = null;
const nestedProps: string[] | null = []; const nestedProps: string[] | null = [];

View File

@ -24,14 +24,17 @@ describe('analyze props', () => {
it('should work', () => { it('should work', () => {
expect( expect(
mock(` mock(`
Component(({foo, bar}) => {}) Component(({foo, bar}) => {
const v = foo + bar;
})
`) `)
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
"Component(() => { "Component(() => {
let foo_$$prop; let foo_$$prop;
let bar_$$prop; let bar_$$prop;
});" const v = foo_$$prop + bar_$$prop;
`); });"
`);
}); });
it('should support default value', () => { it('should support default value', () => {