fix(props): rename the prop without alias and deconstruction
This commit is contained in:
parent
c7de85630e
commit
b15d746697
|
@ -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
|
||||||
|
|
|
@ -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 = [];
|
||||||
|
|
|
@ -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', () => {
|
||||||
|
|
Loading…
Reference in New Issue