Skip to content

Commit eefc091

Browse files
committed
fix: 🐛 出码: 解决 componentName 和 exportName 不一致时生成的 import 语句的问题
1 parent d086267 commit eefc091

File tree

4 files changed

+310
-21
lines changed

4 files changed

+310
-21
lines changed

modules/code-generator/src/plugins/common/esmodule.ts

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { flatMap } from 'lodash';
1+
import { flatMap, camelCase, get } from 'lodash';
22
import { COMMON_CHUNK_NAME } from '../../const/generator';
33

44
import {
@@ -71,6 +71,37 @@ function getDependencyIdentifier(info: IDependencyItem): string {
7171
return info.aliasName || info.exportName;
7272
}
7373

74+
function getExportNameOfDep(dep: IDependency): string {
75+
if (dep.destructuring) {
76+
return (
77+
dep.exportName ||
78+
dep.componentName ||
79+
throwNewError('destructuring dependency must have exportName or componentName')
80+
);
81+
}
82+
83+
if (!dep.subName) {
84+
return (
85+
dep.componentName ||
86+
dep.exportName ||
87+
throwNewError('dependency item must have componentName or exportName')
88+
);
89+
}
90+
91+
return (
92+
dep.exportName ||
93+
`__$${camelCase(
94+
get(dep, 'moduleName') ||
95+
get(dep, 'package') ||
96+
throwNewError('dep.moduleName or dep.package is undefined'),
97+
)}_default`
98+
);
99+
}
100+
101+
function throwNewError(msg: string): never {
102+
throw new Error(msg);
103+
}
104+
74105
function buildPackageImport(
75106
pkg: string,
76107
deps: IDependency[],
@@ -90,7 +121,7 @@ function buildPackageImport(
90121

91122
const depsInfo: IDependencyItem[] = deps.map((dep) => {
92123
const info: IDependencyItem = {
93-
exportName: dep.exportName,
124+
exportName: getExportNameOfDep(dep),
94125
isDefault: !dep.destructuring,
95126
subName: dep.subName || undefined,
96127
nodeIdentifier: dep.componentName || undefined,
@@ -171,24 +202,21 @@ function buildPackageImport(
171202

172203
// 发现 nodeIdentifier 与 exportName 或者 aliasName 冲突的场景
173204
const nodeIdentifiers = depsInfo.map((info) => info.nodeIdentifier).filter(Boolean);
174-
const conflictInfos = flatMap(
175-
Object.keys(exportItems),
176-
(exportName) => {
177-
const exportItem = exportItems[exportName];
178-
const usedNames = [
179-
...exportItem.aliasNames,
180-
...(exportItem.needOriginExport || exportItem.aliasNames.length <= 0 ? [exportName] : []),
205+
const conflictInfos = flatMap(Object.keys(exportItems), (exportName) => {
206+
const exportItem = exportItems[exportName];
207+
const usedNames = [
208+
...exportItem.aliasNames,
209+
...(exportItem.needOriginExport || exportItem.aliasNames.length <= 0 ? [exportName] : []),
210+
];
211+
const conflictNames = usedNames.filter((n) => nodeIdentifiers.indexOf(n) >= 0);
212+
if (conflictNames.length > 0) {
213+
return [
214+
...(conflictNames.indexOf(exportName) >= 0 ? [[exportName, true, exportItem]] : []),
215+
...conflictNames.filter((n) => n !== exportName).map((n) => [n, false, exportItem]),
181216
];
182-
const conflictNames = usedNames.filter((n) => nodeIdentifiers.indexOf(n) >= 0);
183-
if (conflictNames.length > 0) {
184-
return [
185-
...(conflictNames.indexOf(exportName) >= 0 ? [[exportName, true, exportItem]] : []),
186-
...conflictNames.filter((n) => n !== exportName).map((n) => [n, false, exportItem]),
187-
];
188-
}
189-
return [];
190-
},
191-
);
217+
}
218+
return [];
219+
});
192220

193221
const conflictExports = conflictInfos.filter((c) => c[1]).map((c) => c[0] as string);
194222
const conflictAlias = conflictInfos.filter((c) => !c[1]).map((c) => c[0] as string);
@@ -282,6 +310,12 @@ function buildPackageImport(
282310
},
283311
});
284312
} else if (info.aliasName) {
313+
// default 方式的导入会生成单独de import 语句,无需生成赋值语句
314+
if (info.isDefault && defaultExportNames.find((n) => n === info.aliasName)) {
315+
delete aliasDefineStatements[info.aliasName];
316+
return;
317+
}
318+
285319
let contentStatement = '';
286320
if (aliasDefineStatements[info.aliasName]) {
287321
contentStatement = aliasDefineStatements[info.aliasName];

modules/code-generator/test-cases/react-app/demo3/expected/demo-project/src/pages/Test/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Super, {
99
SearchTable as SearchTableExport,
1010
} from "@alifd/next";
1111

12+
import SuperOther from "@alifd/next";
13+
1214
import utils from "../../utils";
1315

1416
import { i18n as _$$i18n } from "../../i18n";
@@ -17,8 +19,6 @@ import "./index.css";
1719

1820
const SuperSub = Super.Sub;
1921

20-
const SuperOther = Super;
21-
2222
const SelectOption = Select.Option;
2323

2424
const SearchTable = SearchTableExport.default;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"version": "1.0.0",
3+
"componentsMap": [
4+
{
5+
"package": "example-package",
6+
"version": "1.2.3",
7+
"exportName": "Bar",
8+
"main": "lib/index.js",
9+
"destructuring": false,
10+
"subName": "",
11+
"componentName": "Foo"
12+
}
13+
],
14+
"componentsTree": [
15+
{
16+
"componentName": "Page",
17+
"id": "node_ocl137q7oc1",
18+
"fileName": "test",
19+
"props": { "style": {} },
20+
"lifeCycles": {},
21+
"dataSource": { "list": [] },
22+
"state": {},
23+
"methods": {},
24+
"children": [
25+
{
26+
"componentName": "Foo",
27+
"id": "node_ocl137q7oc4",
28+
"props": {}
29+
}
30+
]
31+
}
32+
],
33+
"i18n": {}
34+
}
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import CodeGenerator from '../../src';
2+
import * as fs from 'fs';
3+
import * as path from 'path';
4+
import { ProjectSchema } from '@alilc/lowcode-types';
5+
6+
const testCaseBaseName = path.basename(__filename, '.test.ts');
7+
const inputSchemaJsonFile = path.join(__dirname, `${testCaseBaseName}.schema.json`);
8+
const outputDir = path.join(__dirname, `${testCaseBaseName}.generated`);
9+
10+
jest.setTimeout(60 * 60 * 1000);
11+
12+
describe(testCaseBaseName, () => {
13+
test('default import', async () => {
14+
await exportProject(inputSchemaJsonFile, outputDir, {
15+
componentsMap: [
16+
{
17+
package: 'example-package',
18+
version: '1.2.3',
19+
exportName: 'Bar',
20+
main: 'lib/index.js',
21+
destructuring: false,
22+
subName: '',
23+
componentName: 'Foo',
24+
},
25+
],
26+
});
27+
28+
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
29+
expect(generatedPageFileContent).toContain(`import Foo from "example-package/lib/index.js";`);
30+
});
31+
32+
test('named import with no alias', async () => {
33+
await exportProject(inputSchemaJsonFile, outputDir, {
34+
componentsMap: [
35+
{
36+
package: 'example-package',
37+
version: '1.2.3',
38+
exportName: 'Foo',
39+
main: 'lib/index.js',
40+
destructuring: true,
41+
subName: '',
42+
componentName: 'Foo',
43+
},
44+
],
45+
});
46+
47+
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
48+
expect(generatedPageFileContent).toContain(
49+
`import { Foo } from "example-package/lib/index.js";`,
50+
);
51+
});
52+
53+
test('named import with alias', async () => {
54+
await exportProject(inputSchemaJsonFile, outputDir, {
55+
componentsMap: [
56+
{
57+
package: 'example-package',
58+
version: '1.2.3',
59+
exportName: 'Bar',
60+
main: 'lib/index.js',
61+
destructuring: true,
62+
subName: '',
63+
componentName: 'Foo',
64+
},
65+
],
66+
});
67+
68+
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
69+
expect(generatedPageFileContent).toContain(
70+
`import { Bar as Foo } from "example-package/lib/index.js";`,
71+
);
72+
});
73+
74+
test('default import with same name', async () => {
75+
await exportProject(inputSchemaJsonFile, outputDir, {
76+
componentsMap: [
77+
{
78+
package: 'example-package',
79+
version: '1.2.3',
80+
exportName: 'Foo',
81+
main: 'lib/index.js',
82+
destructuring: false,
83+
subName: '',
84+
componentName: 'Foo',
85+
},
86+
],
87+
});
88+
89+
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
90+
expect(generatedPageFileContent).toContain(`import Foo from "example-package/lib/index.js";`);
91+
});
92+
93+
test('default import with sub name and export name', async () => {
94+
await exportProject(inputSchemaJsonFile, outputDir, {
95+
componentsMap: [
96+
{
97+
package: 'example-package',
98+
version: '1.2.3',
99+
exportName: 'Bar',
100+
main: 'lib/index.js',
101+
destructuring: false,
102+
subName: 'Baz',
103+
componentName: 'Foo',
104+
},
105+
],
106+
});
107+
108+
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
109+
expect(generatedPageFileContent).toContain(`import Bar from "example-package/lib/index.js";`);
110+
111+
expect(generatedPageFileContent).toContain(`const Foo = Bar.Baz;`);
112+
});
113+
114+
test('default import with sub name without export name', async () => {
115+
await exportProject(inputSchemaJsonFile, outputDir, {
116+
componentsMap: [
117+
{
118+
package: 'example-package',
119+
version: '1.2.3',
120+
main: 'lib/index.js',
121+
destructuring: false,
122+
exportName: '',
123+
subName: 'Baz',
124+
componentName: 'Foo',
125+
},
126+
],
127+
});
128+
129+
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
130+
expect(generatedPageFileContent).toContain(
131+
`import __$examplePackage_default from "example-package/lib/index.js";`,
132+
);
133+
134+
expect(generatedPageFileContent).toContain(`const Foo = __$examplePackage_default.Baz;`);
135+
});
136+
137+
test('named import with sub name', async () => {
138+
await exportProject(inputSchemaJsonFile, outputDir, {
139+
componentsMap: [
140+
{
141+
package: 'example-package',
142+
version: '1.2.3',
143+
exportName: 'Bar',
144+
main: 'lib/index.js',
145+
destructuring: true,
146+
subName: 'Baz',
147+
componentName: 'Foo',
148+
},
149+
],
150+
});
151+
152+
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
153+
expect(generatedPageFileContent).toContain(
154+
`import { Bar } from "example-package/lib/index.js";`,
155+
);
156+
157+
expect(generatedPageFileContent).toContain(`const Foo = Bar.Baz;`);
158+
});
159+
160+
test('default imports with different componentName', async () => {
161+
await exportProject(inputSchemaJsonFile, outputDir, {
162+
componentsMap: [
163+
{
164+
package: 'example-package',
165+
version: '1.2.3',
166+
exportName: 'Bar',
167+
destructuring: false,
168+
componentName: 'Foo',
169+
},
170+
{
171+
package: 'example-package',
172+
version: '1.2.3',
173+
exportName: 'Bar',
174+
destructuring: false,
175+
componentName: 'Baz',
176+
},
177+
],
178+
componentsTree: [
179+
{
180+
componentName: 'Page',
181+
fileName: 'test',
182+
dataSource: { list: [] },
183+
children: [{ componentName: 'Foo' }, { componentName: 'Baz' }],
184+
},
185+
],
186+
});
187+
188+
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
189+
expect(generatedPageFileContent).toContain(`import Foo from "example-package";`);
190+
expect(generatedPageFileContent).toContain(`import Baz from "example-package";`);
191+
192+
expect(generatedPageFileContent).not.toContain(`const Foo =`);
193+
expect(generatedPageFileContent).not.toContain(`const Baz =`);
194+
});
195+
});
196+
197+
function exportProject(
198+
importPath: string,
199+
outputPath: string,
200+
mergeSchema?: Partial<ProjectSchema>,
201+
) {
202+
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
203+
const schema = { ...JSON.parse(schemaJsonStr), ...mergeSchema };
204+
const builder = CodeGenerator.solutions.icejs();
205+
206+
return builder.generateProject(schema).then(async (result) => {
207+
// displayResultInConsole(result);
208+
const publisher = CodeGenerator.publishers.disk();
209+
await publisher.publish({
210+
project: result,
211+
outputPath,
212+
projectSlug: 'demo-project',
213+
createProjectFolder: true,
214+
});
215+
return result;
216+
});
217+
}
218+
219+
function readOutputTextFile(outputFilePath: string): string {
220+
return fs.readFileSync(path.resolve(outputDir, outputFilePath), 'utf-8');
221+
}

0 commit comments

Comments
 (0)