feat: 🎸 完善 Rax 出码, 跑通第一个测试用例👏👏👏

This commit is contained in:
牧毅 2020-08-12 11:39:15 +08:00
parent c46af6376f
commit 9f621101b3
11 changed files with 307 additions and 25 deletions

View File

@ -0,0 +1 @@
test-cases/

View File

@ -8,6 +8,7 @@
"demo" "demo"
], ],
"scripts": { "scripts": {
"start": "ava --watch",
"build": "rimraf lib && tsc", "build": "rimraf lib && tsc",
"demo": "node ./demo/demo.js", "demo": "node ./demo/demo.js",
"test": "ava", "test": "ava",
@ -45,6 +46,11 @@
], ],
"require": [ "require": [
"ts-node/register/transpile-only" "ts-node/register/transpile-only"
],
"sources": [
"src/**/*",
"test/**/*",
"test-cases/**/expected/**/*"
] ]
}, },
"publishConfig": { "publishConfig": {

View File

@ -21,6 +21,7 @@ export const CLASS_DEFINE_CHUNK_NAME = {
InsVar: 'CommonClassDefineInsVar', InsVar: 'CommonClassDefineInsVar',
InsVarMethod: 'CommonClassDefineInsVarMethod', InsVarMethod: 'CommonClassDefineInsVarMethod',
InsMethod: 'CommonClassDefineInsMethod', InsMethod: 'CommonClassDefineInsMethod',
InsPrivateMethod: 'CommonClassDefineInsPrivateMethod',
End: 'CommonClassDefineEnd', End: 'CommonClassDefineEnd',
}; };
@ -82,6 +83,15 @@ export const DEFAULT_LINK_AFTER = {
CLASS_DEFINE_CHUNK_NAME.InsVarMethod, CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
], ],
[CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod]: [
CLASS_DEFINE_CHUNK_NAME.Start,
CLASS_DEFINE_CHUNK_NAME.StaticVar,
CLASS_DEFINE_CHUNK_NAME.StaticMethod,
CLASS_DEFINE_CHUNK_NAME.InsVar,
CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
CLASS_DEFINE_CHUNK_NAME.InsMethod,
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
],
[CLASS_DEFINE_CHUNK_NAME.End]: [ [CLASS_DEFINE_CHUNK_NAME.End]: [
CLASS_DEFINE_CHUNK_NAME.Start, CLASS_DEFINE_CHUNK_NAME.Start,
CLASS_DEFINE_CHUNK_NAME.StaticVar, CLASS_DEFINE_CHUNK_NAME.StaticVar,
@ -89,6 +99,7 @@ export const DEFAULT_LINK_AFTER = {
CLASS_DEFINE_CHUNK_NAME.InsVar, CLASS_DEFINE_CHUNK_NAME.InsVar,
CLASS_DEFINE_CHUNK_NAME.InsVarMethod, CLASS_DEFINE_CHUNK_NAME.InsVarMethod,
CLASS_DEFINE_CHUNK_NAME.InsMethod, CLASS_DEFINE_CHUNK_NAME.InsMethod,
CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd, CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
], ],
[COMMON_CHUNK_NAME.FileMainContent]: [ [COMMON_CHUNK_NAME.FileMainContent]: [

View File

@ -1,9 +1,9 @@
export const RAX_CHUNK_NAME = { export const RAX_CHUNK_NAME = {
ClassDidMountStart: 'RaxComponentClassDidMountStart',
ClassDidMountContent: 'RaxComponentClassDidMountContent',
ClassDidMountEnd: 'RaxComponentClassDidMountEnd',
ClassRenderStart: 'RaxComponentClassRenderStart', ClassRenderStart: 'RaxComponentClassRenderStart',
ClassRenderPre: 'RaxComponentClassRenderPre', ClassRenderPre: 'RaxComponentClassRenderPre',
ClassRenderEnd: 'RaxComponentClassRenderEnd',
ClassRenderJSX: 'RaxComponentClassRenderJSX', ClassRenderJSX: 'RaxComponentClassRenderJSX',
ClassDidMountStart: 'RaxComponentClassDidMountStart', ClassRenderEnd: 'RaxComponentClassRenderEnd',
ClassDidMountEnd: 'RaxComponentClassDidMountEnd',
ClassDidMountContent: 'RaxComponentClassDidMountContent',
}; };

View File

@ -35,12 +35,17 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
], ],
}); });
next.chunks.push({ next.chunks.push({
type: ChunkType.STRING, type: ChunkType.STRING,
fileType: FileType.JSX, fileType: FileType.JSX,
name: CLASS_DEFINE_CHUNK_NAME.End, name: CLASS_DEFINE_CHUNK_NAME.End,
content: `}`, content: `}`,
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, RAX_CHUNK_NAME.ClassRenderEnd], linkAfter: [
CLASS_DEFINE_CHUNK_NAME.Start,
RAX_CHUNK_NAME.ClassRenderEnd,
CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
],
}); });
// next.chunks.push({ // next.chunks.push({
@ -62,15 +67,36 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
// ], // ],
// }); // });
next.chunks.push({
type: ChunkType.STRING,
fileType: FileType.JSX,
name: RAX_CHUNK_NAME.ClassDidMountStart,
content: `componentDidMount() {`,
linkAfter: [
CLASS_DEFINE_CHUNK_NAME.Start,
CLASS_DEFINE_CHUNK_NAME.InsVar,
CLASS_DEFINE_CHUNK_NAME.InsMethod,
],
});
next.chunks.push({
type: ChunkType.STRING,
fileType: FileType.JSX,
name: RAX_CHUNK_NAME.ClassDidMountEnd,
content: `}`,
linkAfter: [
RAX_CHUNK_NAME.ClassDidMountStart,
RAX_CHUNK_NAME.ClassDidMountContent,
],
});
next.chunks.push({ next.chunks.push({
type: ChunkType.STRING, type: ChunkType.STRING,
fileType: FileType.JSX, fileType: FileType.JSX,
name: RAX_CHUNK_NAME.ClassRenderStart, name: RAX_CHUNK_NAME.ClassRenderStart,
content: 'render() {', content: 'render() {',
linkAfter: [ linkAfter: [
CLASS_DEFINE_CHUNK_NAME.Start, RAX_CHUNK_NAME.ClassDidMountEnd,
CLASS_DEFINE_CHUNK_NAME.ConstructorEnd,
CLASS_DEFINE_CHUNK_NAME.InsMethod,
], ],
}); });
@ -79,11 +105,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
fileType: FileType.JSX, fileType: FileType.JSX,
name: RAX_CHUNK_NAME.ClassRenderEnd, name: RAX_CHUNK_NAME.ClassRenderEnd,
content: '}', content: '}',
linkAfter: [ linkAfter: [RAX_CHUNK_NAME.ClassRenderStart, RAX_CHUNK_NAME.ClassRenderPre, RAX_CHUNK_NAME.ClassRenderJSX],
RAX_CHUNK_NAME.ClassRenderStart,
RAX_CHUNK_NAME.ClassRenderPre,
RAX_CHUNK_NAME.ClassRenderJSX,
],
}); });
next.chunks.push({ next.chunks.push({

View File

@ -0,0 +1,86 @@
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
import {
BuilderComponentPlugin,
BuilderComponentPluginFactory,
ChunkType,
FileType,
ICodeStruct,
} from '../../../types';
import { RAX_CHUNK_NAME } from './const';
type PluginConfig = {
fileType: string;
}
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
const cfg: PluginConfig = {
fileType: FileType.JSX,
...config,
};
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
const next: ICodeStruct = {
...pre,
};
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
content: `
_context = this._createContext();
`,
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
});
// TODO: 补充数据源的定义
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
content: `
_createContext() {
const self = this;
const context = {
get state() {
return self.state;
},
setState(newState) {
self.setState(newState);
},
get dataSourceMap() {
return self._dataSourceEngine?.dataSourceMap || {};
},
async reloadDataSource() {
self._dataSourceEngine?.reloadDataSource();
},
get utils() {
return self._utils;
},
get page() {
return context;
},
get component() {
return context;
},
get props() {
return self.props;
},
};
return context;
}
`,
linkAfter: [
RAX_CHUNK_NAME.ClassRenderEnd
],
});
return next;
};
return plugin;
};
export default pluginFactory;

View File

@ -0,0 +1,78 @@
import { CLASS_DEFINE_CHUNK_NAME, COMMON_CHUNK_NAME } from '../../../const/generator';
import {
BuilderComponentPlugin,
BuilderComponentPluginFactory,
ChunkType,
FileType,
ICodeStruct,
} from '../../../types';
import { RAX_CHUNK_NAME } from './const';
type PluginConfig = {
fileType: string;
}
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
const cfg: PluginConfig = {
fileType: FileType.JSX,
...config,
};
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
const next: ICodeStruct = {
...pre,
};
next.chunks.push({
type: ChunkType.STRING,
fileType: FileType.JSX,
name: COMMON_CHUNK_NAME.ExternalDepsImport,
content: `
import { createDataSourceEngine } from '@ali/lowcode-data-source-engine';
`,
linkAfter: [],
});
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
content: `
_dataSourceList = this._defineDataSourceList();
_dataSourceEngine = createDataSourceEngine(this._dataSourceList, this._context);`,
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
});
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: RAX_CHUNK_NAME.ClassDidMountContent,
content: `
this._dataSourceEngine.reloadDataSource();
`,
linkAfter: [
RAX_CHUNK_NAME.ClassDidMountStart,
],
});
// TODO: 补充数据源的定义
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
content: `
_defineDataSourceList() {
return [];
}`,
linkAfter: [
RAX_CHUNK_NAME.ClassRenderEnd
],
});
return next;
};
return plugin;
};
export default pluginFactory;

View File

@ -7,6 +7,7 @@ import {
FileType, FileType,
ICodeStruct, ICodeStruct,
} from '../../../types'; } from '../../../types';
import { RAX_CHUNK_NAME } from './const';
type PluginConfig = { type PluginConfig = {
fileType: string; fileType: string;
@ -24,13 +25,27 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
}; };
// TODO: utils 怎么注入? // TODO: utils 怎么注入?
// next.chunks.push({ next.chunks.push({
// type: ChunkType.STRING, type: ChunkType.STRING,
// fileType: cfg.fileType, fileType: cfg.fileType,
// name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent, name: CLASS_DEFINE_CHUNK_NAME.InsVar,
// content: `this.utils = utils;`, content: `_utils = this._defineUtils();`,
// linkAfter: [CLASS_DEFINE_CHUNK_NAME.ConstructorStart], linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
// }); });
next.chunks.push({
type: ChunkType.STRING,
fileType: cfg.fileType,
name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
content: `
_defineUtils() {
return {};
}`,
linkAfter: [
RAX_CHUNK_NAME.ClassRenderEnd
],
});
return next; return next;
}; };

View File

@ -40,7 +40,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
fileType: FileType.JSX, fileType: FileType.JSX,
name: CLASS_DEFINE_CHUNK_NAME.End, name: CLASS_DEFINE_CHUNK_NAME.End,
content: `}`, content: `}`,
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start, REACT_CHUNK_NAME.ClassRenderEnd], linkAfter: [
CLASS_DEFINE_CHUNK_NAME.Start,
REACT_CHUNK_NAME.ClassRenderEnd,
],
}); });
next.chunks.push({ next.chunks.push({

View File

@ -4,10 +4,12 @@ import { createProjectBuilder } from '../generator/ProjectBuilder';
import esModule from '../plugins/common/esmodule'; import esModule from '../plugins/common/esmodule';
import containerClass from '../plugins/component/rax/containerClass'; import containerClass from '../plugins/component/rax/containerClass';
import containerInitState from '../plugins/component/rax/containerInitState';
import containerInjectUtils from '../plugins/component/rax/containerInjectUtils';
import containerLifeCycle from '../plugins/component/rax/containerLifeCycle'; import containerLifeCycle from '../plugins/component/rax/containerLifeCycle';
import containerMethod from '../plugins/component/rax/containerMethod'; import containerMethod from '../plugins/component/rax/containerMethod';
import containerInitState from '../plugins/component/rax/containerInitState';
import containerInjectContext from '../plugins/component/rax/containerInjectContext';
import containerInjectDataSourceEngine from '../plugins/component/rax/containerInjectDataSourceEngine';
import containerInjectUtils from '../plugins/component/rax/containerInjectUtils';
import jsx from '../plugins/component/rax/jsx'; import jsx from '../plugins/component/rax/jsx';
import commonDeps from '../plugins/component/rax/commonDeps'; import commonDeps from '../plugins/component/rax/commonDeps';
import css from '../plugins/component/style/css'; import css from '../plugins/component/style/css';
@ -42,8 +44,10 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
fileType: 'jsx', fileType: 'jsx',
}), }),
containerClass(), containerClass(),
containerInjectUtils(),
containerInitState(), containerInitState(),
containerInjectContext(),
containerInjectDataSourceEngine(),
containerInjectUtils(),
containerLifeCycle(), containerLifeCycle(),
containerMethod(), containerMethod(),
jsx(), jsx(),
@ -58,6 +62,8 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
htmlEntry: [raxApp.plugins.entryDocument()], htmlEntry: [raxApp.plugins.entryDocument()],
packageJSON: [raxApp.plugins.packageJSON()], packageJSON: [raxApp.plugins.packageJSON()],
}, },
postProcessors: [prettier()], postProcessors: [
// prettier() // 暂且禁用 prettier
],
}); });
} }

View File

@ -4,9 +4,22 @@ import Page from 'rax-view';
import Text from 'rax-text'; import Text from 'rax-text';
import { createDataSourceEngine } from '@ali/lowcode-data-source-engine';
import './index.css'; import './index.css';
class Home$$Page extends Component { class Home$$Page extends Component {
_context = this._createContext();
_dataSourceList = this._defineDataSourceList();
_dataSourceEngine = createDataSourceEngine(this._dataSourceList, this._context);
_utils = this._defineUtils();
componentDidMount() {
this._dataSourceEngine.reloadDataSource();
}
render() { render() {
return ( return (
<Page> <Page>
@ -14,6 +27,47 @@ class Home$$Page extends Component {
</Page> </Page>
); );
} }
_createContext() {
const self = this;
const context = {
get state() {
return self.state;
},
setState(newState) {
self.setState(newState);
},
get dataSourceMap() {
return self._dataSourceEngine?.dataSourceMap || {};
},
async reloadDataSource() {
self._dataSourceEngine?.reloadDataSource();
},
get utils() {
return self._utils;
},
get page() {
return context;
},
get component() {
return context;
},
get props() {
return self.props;
},
};
return context;
}
_defineDataSourceList() {
return [];
}
_defineUtils() {
return {};
}
} }
export default Home$$Page; export default Home$$Page;