Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DiDi
Chameleon
提交
126916b3
C
Chameleon
项目概览
DiDi
/
Chameleon
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
Chameleon
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
126916b3
编写于
4月 25, 2019
作者:
Y
yylgit
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
component export
上级
37b1a2db
变更
16
展开全部
隐藏空白更改
内联
并排
Showing
16 changed file
with
40 addition
and
1294 deletion
+40
-1294
packages/chameleon-tool-utils/src/index.js
packages/chameleon-tool-utils/src/index.js
+19
-34
packages/chameleon-tool-utils/test/index.test.js
packages/chameleon-tool-utils/test/index.test.js
+16
-1
packages/chameleon-tool-utils/test/testlib/demo-project/src/components/com2/com2.interface
...t/testlib/demo-project/src/components/com2/com2.interface
+2
-0
packages/chameleon-tool-utils/test/testlib/demo-project/src/components/com2/com2.web.cml
...est/testlib/demo-project/src/components/com2/com2.web.cml
+0
-0
packages/chameleon-tool-utils/test/testlib/demo-project/src/components/com2/com2.wx.cml
...test/testlib/demo-project/src/components/com2/com2.wx.cml
+0
-0
packages/chameleon-tool-utils/test/testlib/demo-project/src/components/com3/com3.interface
...t/testlib/demo-project/src/components/com3/com3.interface
+0
-0
packages/mvvm-babel-parser/package.json
packages/mvvm-babel-parser/package.json
+3
-2
packages/mvvm-script-parser/.eslintrc
packages/mvvm-script-parser/.eslintrc
+0
-566
packages/mvvm-script-parser/.gitignore
packages/mvvm-script-parser/.gitignore
+0
-69
packages/mvvm-script-parser/README.md
packages/mvvm-script-parser/README.md
+0
-1
packages/mvvm-script-parser/index.js
packages/mvvm-script-parser/index.js
+0
-190
packages/mvvm-script-parser/lib/check.js
packages/mvvm-script-parser/lib/check.js
+0
-381
packages/mvvm-script-parser/package.json
packages/mvvm-script-parser/package.json
+0
-21
packages/mvvm-script-parser/test/d.js
packages/mvvm-script-parser/test/d.js
+0
-0
packages/mvvm-script-parser/test/dependencies.js
packages/mvvm-script-parser/test/dependencies.js
+0
-29
packages/mvvm-script-parser/test/e.js
packages/mvvm-script-parser/test/e.js
+0
-0
未找到文件。
packages/chameleon-tool-utils/src/index.js
浏览文件 @
126916b3
...
...
@@ -1040,55 +1040,40 @@ function getPluginKey(type, key) {
// 获取export模式的入口cml文件
_
.
getExportEntry
=
function
(
cmlType
,
context
,
entry
=
[])
{
let
exportFiles
=
[];
function
addExport
(
filePath
)
{
if
(
_
.
isFile
(
filePath
)
&&
!~
exportFiles
.
indexOf
(
filePath
))
{
exportFiles
.
push
(
filePath
);
}
}
if
(
entry
&&
entry
.
length
>
0
)
{
entry
.
forEach
(
item
=>
{
let
filePath
=
path
.
join
(
context
,
item
);
// cml文件插入
if
(
_
.
isFile
(
filePath
))
{
exportFiles
.
push
(
filePath
);
if
(
path
.
extname
(
filePath
)
===
'
.cml
'
)
{
exportFiles
.
push
(
filePath
);
}
else
if
(
path
.
extname
(
filePath
)
===
'
.interface
'
)
{
let
content
=
fs
.
readFileSync
(
filePath
,
{
encoding
:
'
utf-8
'
});
let
cmlFilePath
=
_
.
findPolymorphicComponent
(
filePath
,
content
,
cmlType
);
addExport
(
cmlFilePath
);
}
}
else
if
(
_
.
isDirectory
(
filePath
))
{
let
cmlFilePath
=
path
.
join
(
filePath
,
'
**/*.cml
'
);
let
interfaceFilePath
=
path
.
join
(
filePath
,
'
**/*.interface
'
);
// 需要忽略掉的组件
// let ignoreComponents = ['web', 'weex', 'wx', 'alipay', 'baidu'];
// if (~ignoreComponents.indexOf(cmlType)) {
// ignoreComponents.splice(ignoreComponents.indexOf(cmlType), 1);
// }
// ignoreComponents = ignoreComponents.map(item => `\\.${item}\\.cml`);
// let ignoreReg = new RegExp(`(${ignoreComponents.join('|')})`);
// glob.sync(filePath).forEach(cmlPath => {
// // 其他端的多态cml组件排除在外
// if (!ignoreReg.test(cmlPath)) {
// exportFiles.push(cmlPath);
// }
// })
// 多态组件有了include语法之后不能采用上面的方法
// 1 先找interface指定的多态组件
// 2 再找cml文件 不能根据文件名称区分端,如果所有cml文件 也会把其他端多态组件引入,所以取只有一个逗号的cml文件
//
todo
// 2 再找cml文件 不能根据文件名称区分端,如果所有cml文件 也会把其他端多态组件引入,所以取只有一个逗号的cml文件
为非多态组件
//
获取重复添加入口时有校验
glob
.
sync
(
interfaceFilePath
).
forEach
(
interfacePath
=>
{
// 其他端的多态cml组件排除在外
let
content
=
fs
.
readFileSync
(
interfacePath
,
{
encoding
:
'
utf-8
'
});
let
cmlFilePath
=
_
.
findPolymorphicComponent
(
interfacePath
,
content
,
cmlType
);
if
(
_
.
isFile
(
cmlFilePath
))
{
// 组件的名称是interface文件的名称
if
(
!~
exportFiles
.
indexOf
(
cmlFilePath
))
{
exportFiles
.
push
(
cmlFilePath
);
}
}
addExport
(
cmlFilePath
);
})
glob
.
sync
(
cmlFilePath
).
forEach
(
item
=>
{
if
(
_
.
isFile
(
item
))
{
let
basename
=
path
.
basename
(
item
);
if
(
basename
.
split
(
'
.
'
).
length
===
2
)
{
// 组件的名称是interface文件的名称
if
(
!~
exportFiles
.
indexOf
(
cmlFilePath
))
{
exportFiles
.
push
(
cmlFilePath
);
}
}
let
basename
=
path
.
basename
(
item
);
if
(
basename
.
split
(
'
.
'
).
length
===
2
)
{
addExport
(
item
);
}
})
}
...
...
packages/chameleon-tool-utils/test/index.test.js
浏览文件 @
126916b3
...
...
@@ -378,7 +378,6 @@ describe('index.js', function () {
var
cmlFilePath
=
path
.
join
(
__dirname
,
'
testlib/demo-project/src/pages/page1/page1.cml
'
);
var
comrefPath
=
'
vant-weapp/test
'
debugger
let
result
=
_
.
handleComponentUrl
(
cml
.
projectRoot
,
cmlFilePath
,
comrefPath
,
'
wx
'
);
expect
(
result
.
refUrl
).
to
.
equal
(
'
./../../npm/vant-weapp/test
'
);
})
...
...
@@ -685,4 +684,20 @@ describe('index.js', function () {
expect
(
result3
).
to
.
be
.
equal
(
'
name
'
);
})
it
(
`getExportEntry`
,
function
()
{
global
.
cml
=
{};
_
.
setCli
(
true
);
global
.
cml
.
event
=
new
EventEmitter
();
global
.
cml
.
utils
=
_
;
global
.
projectRoot
=
path
.
join
(
__dirname
,
'
testlib/demo-project
'
);
let
result
=
_
.
getExportEntry
(
'
web
'
,
global
.
projectRoot
,
[
'
src/components
'
,
'
src/notfinr.cml
'
,
'
src/components/com2/com2.interface
'
]);
console
.
log
(
result
)
expect
(
result
.
length
).
to
.
be
.
equal
(
2
);
})
})
packages/chameleon-tool-utils/test/testlib/demo-project/src/components/com2/com2.interface
0 → 100644
浏览文件 @
126916b3
<script cml-type="web" src="./com2.web.cml"></script>
<script cml-type="wx" src="./com2.wx.cml"></script>
\ No newline at end of file
packages/
mvvm-script-parser/test/a.js
→
packages/
chameleon-tool-utils/test/testlib/demo-project/src/components/com2/com2.web.cml
浏览文件 @
126916b3
文件已移动
packages/
mvvm-script-parser/test/b.js
→
packages/
chameleon-tool-utils/test/testlib/demo-project/src/components/com2/com2.wx.cml
浏览文件 @
126916b3
文件已移动
packages/
mvvm-script-parser/test/c.js
→
packages/
chameleon-tool-utils/test/testlib/demo-project/src/components/com3/com3.interface
浏览文件 @
126916b3
文件已移动
packages/mvvm-babel-parser/package.json
浏览文件 @
126916b3
...
...
@@ -10,11 +10,12 @@
"dependencies"
:
{
"babel-generator"
:
"6.26.1"
,
"babel-traverse"
:
"6.26.0"
,
"babel-types"
:
"6.26.0"
"babel-types"
:
"6.26.0"
,
"chai"
:
"^4.2.0"
},
"scripts"
:
{
"test"
:
"mocha"
},
"author"
:
""
,
"license"
:
"ISC"
}
\ No newline at end of file
}
packages/mvvm-script-parser/.eslintrc
已删除
100644 → 0
浏览文件 @
37b1a2db
此差异已折叠。
点击以展开。
packages/mvvm-script-parser/.gitignore
已删除
100644 → 0
浏览文件 @
37b1a2db
# Editor directories and files
.DS_Store
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
.vscode
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# ///////////////////////////
packages/mvvm-script-parser/README.md
已删除
100644 → 0
浏览文件 @
37b1a2db
#### mvvm协议标准中处理cml文件script部分与js文件
\ No newline at end of file
packages/mvvm-script-parser/index.js
已删除
100644 → 0
浏览文件 @
37b1a2db
/** 编译源码
* 分析依赖
* */
'
use strict
'
;
const
{
parsePlugins
}
=
require
(
'
runtime-check
'
);
const
parser
=
require
(
'
@babel/parser
'
);
const
babel
=
require
(
'
@babel/core
'
);
const
traverse
=
require
(
'
@babel/traverse
'
);
const
t
=
require
(
'
@babel/types
'
);
const
cmlUtils
=
require
(
'
chameleon-tool-utils
'
);
const
{
getCheckCode
}
=
require
(
'
./lib/check
'
);
const
interfaceParser
=
require
(
'
mvvm-interface-parser
'
);
const
getInterfaceCode
=
require
(
'
mvvm-interface-parser/lib/getInterfaceCode.js
'
);
const
generator
=
require
(
"
@babel/generator
"
);
const
path
=
require
(
'
path
'
);
const
defaultResolve
=
function
(
filePath
,
relativePath
)
{
return
path
.
resolve
(
path
.
dirname
(
filePath
),
relativePath
)
}
// 标准的script部分处理
exports
.
standardParser
=
function
({
cmlType
,
media
,
source
,
filePath
,
check
,
resolve
=
defaultResolve
})
{
let
devDeps
=
[];
let
reg
=
new
RegExp
(
`\\.
${
cmlType
}
\\.cml$`
);
// 多态组件 获取interface文件并拼接
if
(
reg
.
test
(
filePath
))
{
let
interfacePath
=
cmlUtils
.
RecordCml2Interface
[
filePath
];
if
(
!
interfacePath
)
{
throw
new
Error
(
`not find interface for
${
filePath
}
`
)
}
let
{
content
:
interfaceCode
,
devDeps
:
interfaceDevDeps
,
contentFilePath
}
=
getInterfaceCode
({
interfacePath
});
devDeps
=
interfaceDevDeps
;
if
(
media
===
'
dev
'
&&
check
.
enable
===
true
)
{
try
{
source
=
getCheckCode
(
interfaceCode
,
source
,
contentFilePath
,
filePath
,
cmlType
,
check
.
enableTypes
);
}
catch
(
e
)
{
// 当有语法错误 babel parse会报错,报错信息不友好
cmlUtils
.
log
.
error
(
`mvvm-interface-parser:
${
filePath
}
or
${
contentFilePath
}
syntax error!`
)
}
}
}
// .interface文件
else
if
(
/
\.
interface$/
.
test
(
filePath
))
{
let
interfaceResult
=
interfaceParser
({
cmlType
,
media
,
source
,
filePath
,
check
,
resolve
});
source
=
interfaceResult
.
result
;
devDeps
=
interfaceResult
.
devDeps
;
}
return
{
source
,
devDeps
};
}
// 源代码的ast
exports
.
JSCompile
=
function
({
source
,
filePath
,
compiler
})
{
const
ast
=
exports
.
getAST
({
source
});
const
dependencies
=
exports
.
getDependenciesAndReplace
({
ast
,
filePath
,
compiler
});
const
output
=
generator
[
"
default
"
](
ast
);
return
{
ast
,
dependencies
,
output
};
}
// 获取ast
exports
.
getAST
=
function
({
source
})
{
const
ast
=
parser
.
parse
(
source
,
{
sourceType
:
'
module
'
,
plugins
:
parsePlugins
});
return
ast
;
}
// 获取dependencies
exports
.
getDependenciesAndReplace
=
function
({
ast
,
filePath
,
compiler
})
{
let
dependencies
=
[];
traverse
[
"
default
"
](
ast
,
{
enter
:
(
path
)
=>
{
let
node
=
path
.
node
;
if
(
t
.
isImportDeclaration
(
node
)
&&
node
.
source
.
value
)
{
let
{
realPath
,
modId
}
=
getJSModId
(
node
.
source
.
value
);
node
.
source
.
value
=
modId
;
node
.
source
.
raw
=
`'
${
modId
}
'`
;
dependencies
.
push
(
realPath
);
}
if
(
t
.
isVariableDeclaration
(
node
))
{
node
.
declarations
.
forEach
(
item
=>
{
if
(
item
&&
item
.
init
&&
item
.
init
.
callee
&&
item
.
init
.
callee
.
name
===
'
require
'
&&
item
.
init
.
arguments
&&
item
.
init
.
arguments
[
0
]
&&
item
.
init
.
arguments
[
0
].
value
)
{
let
{
realPath
,
modId
}
=
getJSModId
(
item
.
init
.
arguments
[
0
].
value
);
item
.
init
.
arguments
[
0
].
value
=
modId
;
item
.
init
.
arguments
[
0
].
raw
=
`'
${
modId
}
'`
;
dependencies
.
push
(
realPath
);
}
})
}
if
(
t
.
isExpressionStatement
(
node
)
&&
node
.
expression
&&
node
.
expression
.
callee
&&
node
.
expression
.
callee
.
name
===
'
require
'
&&
node
.
expression
.
arguments
&&
node
.
expression
.
arguments
[
0
])
{
let
{
realPath
,
modId
}
=
getJSModId
(
node
.
expression
.
arguments
[
0
].
value
);
node
.
expression
.
arguments
[
0
].
value
=
modId
;
node
.
expression
.
arguments
[
0
].
raw
=
`'
${
modId
}
'`
;
dependencies
.
push
(
realPath
);
}
}
})
function
getJSModId
(
dependPath
)
{
if
(
compiler
)
{
let
realDependPath
=
compiler
.
resolve
(
filePath
,
dependPath
);
return
{
realPath
:
realDependPath
,
modId
:
compiler
.
createModId
(
realDependPath
)
};
}
else
{
return
{
realPath
:
dependPath
,
modId
:
dependPath
}
}
}
return
dependencies
;
}
// 获取dependencies
exports
.
getDependencies
=
function
({
ast
})
{
let
dependencies
=
[];
traverse
[
"
default
"
](
ast
,
{
enter
:
(
path
)
=>
{
let
node
=
path
.
node
;
if
(
t
.
isImportDeclaration
(
node
)
&&
node
.
source
.
value
)
{
dependencies
.
push
(
node
.
source
.
value
);
}
if
(
t
.
isVariableDeclaration
(
node
))
{
node
.
declarations
.
forEach
(
item
=>
{
if
(
item
&&
item
.
init
&&
item
.
init
.
callee
&&
item
.
init
.
callee
.
name
===
'
require
'
&&
item
.
init
.
arguments
&&
item
.
init
.
arguments
[
0
]
&&
item
.
init
.
arguments
[
0
].
value
)
{
dependencies
.
push
(
item
.
init
.
arguments
[
0
].
value
);
}
})
}
if
(
t
.
isExpressionStatement
(
node
)
&&
node
.
expression
&&
node
.
expression
.
callee
&&
node
.
expression
.
callee
.
name
===
'
require
'
&&
node
.
expression
.
arguments
&&
node
.
expression
.
arguments
[
0
])
{
dependencies
.
push
(
node
.
expression
.
arguments
[
0
].
value
);
}
}
})
return
dependencies
;
}
// 提供标准的jsbabel方法
exports
.
standardBabel
=
function
({
source
,
options
})
{
// options 这里需要兼容
options
=
options
||
exports
.
standardBabelOptions
;
let
output
=
babel
.
transformSync
(
source
,
options
);
// => { code, map, ast }
return
output
;
}
exports
.
standardBabelOptions
=
{
"
presets
"
:
[
"
flow
"
,
[
"
env
"
,
{
"
targets
"
:
{
"
browsers
"
:
[
"
> 1%
"
,
"
last 2 versions
"
,
"
not ie <= 8
"
]
}
}
],
"
stage-0
"
],
"
plugins
"
:
[
"
transform-remove-strict-mode
"
,
[
"
transform-runtime
"
,
{
"
helpers
"
:
false
,
"
polyfill
"
:
false
,
"
regenerator
"
:
true
,
"
moduleName
"
:
"
babel-runtime
"
}],
[
"
babel-plugin-chameleon-import
"
,
{
"
libraryName
"
:
"
chameleon-api
"
,
"
libraryDirectory
"
:
"
src/interfaces
"
,
"
libraryFileName
"
:
"
index.js
"
,
"
defaulLibraryDirectory
"
:
""
,
"
defaulLibraryFileName
"
:
"
index.js
"
}]
]
}
packages/mvvm-script-parser/lib/check.js
已删除
100644 → 0
浏览文件 @
37b1a2db
/* eslint-disable */
/**
* cml多态组件 interface校验
* 1 拿到interface的校验
* 2 写好处理default对象的方法
* 3 拼接代码
*/
const
path
=
require
(
'
path
'
);
const
parser
=
require
(
'
@babel/parser
'
);
const
traverse
=
require
(
'
@babel/traverse
'
);
const
generate
=
require
(
"
@babel/generator
"
);
const
{
getDefines
,
parsePlugins
}
=
require
(
'
runtime-check
'
);
const
cmlUtils
=
require
(
'
chameleon-tool-utils
'
);
/**
* 处理对象的函数
* @param {*} obj
*/
function
wrapper
(
obj
)
{
const
className
=
obj
.
constructor
.
name
;
const
interfaceDefines
=
__INTERFAE__DEFINES__
;
const
enableTypes
=
__enableTypes__
;
// ['Object','Array','Nullable']
const
types
=
interfaceDefines
.
types
;
const
interfaceKey
=
Object
.
keys
(
interfaceDefines
.
interfaces
)[
0
];
// interface Name
const
interfaceObj
=
interfaceDefines
.
interfaces
[
interfaceKey
];
const
cmlDefines
=
__CML__DEFINES__
;
let
isImplementInterface
=
false
;
// 找到class
if
(
cmlDefines
.
classes
[
className
])
{
// class 的interface数组中有interface中的定义
if
(
~
cmlDefines
.
classes
[
className
].
indexOf
(
interfaceKey
))
{
isImplementInterface
=
true
;
}
else
{
console
.
error
(
`class
${
className
}
not implements interface
${
interfaceKey
}
`
);
}
}
let
props
=
[];
let
events
=
{};
Object
.
keys
(
interfaceObj
).
forEach
(
key
=>
{
let
item
=
interfaceObj
[
key
];
if
(
is
(
item
,
'
Object
'
))
{
// 是事件 有output和input
events
[
key
]
=
item
;
}
else
{
// 是属性
props
.
push
({
key
,
value
:
item
})
}
})
// created 时做props校验 同时建立watch属性检测props类型
// 包装this.$cmlEmit 校验自定义事件参数类型
function
isFunc
(
target
)
{
return
target
&&
is
(
target
,
'
Function
'
)
}
function
is
(
source
,
type
)
{
return
Object
.
prototype
.
toString
.
call
(
source
)
===
'
[object
'
+
type
+
'
]
'
;
}
const
getType
=
function
(
value
)
{
const
type
=
Object
.
prototype
.
toString
.
call
(
value
);
return
type
.
replace
(
/
\[
object
\s(
.*
)\]
/g
,
'
$1
'
).
replace
(
/
(
|^
)[
a-z
]
/g
,
(
L
)
=>
L
.
toUpperCase
());
};
// beforeCreate时 vue中还获取不到mixins的this.$cmlEmit方法
let
oldCreated
=
obj
.
created
||
function
()
{};
obj
.
created
=
function
(...
args
)
{
checkProps
.
call
(
this
);
oldCreated
.
call
(
this
);
}
obj
.
methods
=
obj
.
methods
||
{};
obj
.
methods
.
$__checkCmlEmit__
=
function
(
eventName
,
eventDetail
)
{
if
(
events
[
eventName
])
{
let
{
input
}
=
events
[
eventName
];
let
detailType
=
input
[
0
];
let
errList
=
checkType
(
eventDetail
,
detailType
,
[]);
if
(
errList
&&
errList
.
length
)
{
showErrorMessage
(
`errorinfo: event
${
eventName
}
detail verification fails
${
errList
.
join
(
'
\n
'
)}
`
)
}
}
else
{
showErrorMessage
(
`errorinfo: event
${
eventName
}
is not defined in interface
${
errList
.
join
(
'
\n
'
)}
`
)
}
}
function
checkProps
()
{
props
.
forEach
(
item
=>
{
let
errList
=
checkType
(
this
[
item
.
key
],
item
.
value
,
[]);
if
(
errList
&&
errList
.
length
)
{
showErrorMessage
(
`error: prop [
${
item
.
key
}
] verification fails
${
errList
.
join
(
'
\n
'
)}
`
)
}
})
}
obj
.
watch
=
obj
.
watch
||
{};
props
.
forEach
(
item
=>
{
let
oldWatch
=
obj
.
watch
[
item
.
key
];
obj
.
watch
[
item
.
key
]
=
function
(
newVal
,
oldVal
)
{
let
errList
=
checkType
(
newVal
,
item
.
value
,
[]);
if
(
errList
&&
errList
.
length
)
{
showErrorMessage
(
`errorinfo: prop [
${
item
.
key
}
] verification fails
${
errList
.
join
(
'
\n
'
)}
`
)
}
if
(
isFunc
(
oldWatch
))
{
oldWatch
.
call
(
this
,
newVal
,
oldVal
);
}
}
})
/**
* 校验类型 两个loader共用代码
*
* @param {*} value 实际传入的值
* @param {string} type 静态分析时候得到的值得类型
* @param {array[string]} errList 校验错误信息 类型
* @return {bool} 校验结果
*/
const
checkType
=
function
(
value
,
originType
,
errList
=
[])
{
let
isNullableReg
=
/_cml_nullable_lmc_/g
;
let
type
=
originType
.
replace
(
'
_cml_nullable_lmc_
'
,
''
);
(
type
===
"
Void
"
)
&&
(
type
=
"
Undefined
"
)
let
currentType
=
getType
(
value
);
// Undefined Null Object Array Number String Function只可能是这几种类型;
// 但是对于type的值则可能是 Undefined Null Number String NullUndefinedStiring
// Object Array Function EventDetail(...这种自定义的复杂数据类型) 这几种;
// 判断nullable类型的参数
// 如果 currentType === type 那么就会直接返回 [];
let
canUseNullable
=
enableTypes
.
includes
(
"
Nullable
"
);
let
canUseObject
=
enableTypes
.
includes
(
"
Object
"
);
let
canUseArray
=
enableTypes
.
includes
(
"
Array
"
);
if
(
currentType
==
'
Null
'
)
{
// 如果传入的值是 null类型,那么可能的情况是该值在接口处的被定义为Null或者是 ?string 这种可选参数的形式;
if
(
type
==
"
Null
"
)
{
// 如果定义的参数的值就是 Null,那么校验通过
errList
=
[];
}
else
{
// 实际定义的参数的值不是 Null ?string这种形式的定义,type = new String('String') ?Callback type = new String('Callback')
// 那么判断是否是可选参数的情况
(
canUseNullable
&&
isNullableReg
.
test
(
originType
))
?
errList
=
[]
:
errList
.
push
(
`定义了
${
type
}
类型的参数,传入的却是
${
currentType
}
,请确认是否开启nullable配置`
)
}
return
errList
;
}
if
(
currentType
==
'
Undefined
'
)
{
// 如果运行时传入的真实值是undefined,那么可能改值在接口处就是被定义为 Undefined类型或者是 ?string 这种可选参数 nullable的情况;
if
(
type
==
"
Undefined
"
)
{
errList
=
[];
}
else
{
(
canUseNullable
&&
isNullableReg
.
test
(
originType
))
?
errList
=
[]
:
errList
.
push
(
`定义了
${
type
}
类型的参数,传入的却是
${
currentType
}
,请确认是否开启nullable配置或者检查所传参数是否和接口定义的一致`
)
}
return
errList
;
}
if
(
currentType
==
'
String
'
)
{
if
(
type
==
'
String
'
)
{
errList
=
[];
}
else
{
errList
.
push
(
`定义了
${
type
}
类型的参数,传入的却是
${
currentType
}
,请检查所传参数是否和接口定义的一致`
)
}
return
errList
;
}
if
(
currentType
==
'
Boolean
'
)
{
if
(
type
==
'
Boolean
'
)
{
errList
=
[];
}
else
{
errList
.
push
(
`定义了
${
type
}
类型的参数,传入的却是
${
currentType
}
,请检查所传参数是否和接口定义的一致`
)
}
return
errList
;
}
if
(
currentType
==
'
Number
'
)
{
if
(
type
==
'
Number
'
)
{
errList
=
[];
}
else
{
errList
.
push
(
`定义了
${
type
}
类型的参数,传入的却是
${
currentType
}
,请检查所传参数是否和接口定义的一致`
)
}
return
errList
;
}
if
(
currentType
==
'
Object
'
)
{
if
(
type
==
'
Object
'
)
{
(
!
canUseObject
)
?
errList
.
push
(
`不能直接定义类型
${
type
}
,需要使用符合类型定义,请确认是否开启了可以直接定义 Object 类型参数;`
)
:
(
errList
=
[]);
}
else
if
(
type
==
'
CMLObject
'
)
{
errList
=
[];
}
else
{
// 这种情况的对象就是自定义的对象;
if
(
types
[
type
])
{
const
keys
=
Object
.
keys
(
types
[
type
]);
// todo 这里是同样的问题,可能多传递
keys
.
forEach
(
key
=>
{
let
subError
=
checkType
(
value
[
key
],
types
[
type
][
key
],
[]);
if
(
subError
&&
subError
.
length
)
{
errList
=
errList
.
concat
(
subError
)
}
});
if
(
Object
.
keys
(
value
).
length
>
keys
.
length
)
{
errList
.
push
(
`type [
${
type
}
] 参数个数与定义不符`
)
}
}
else
{
errList
.
push
(
'
找不到定义的type [
'
+
type
+
'
]!
'
);
}
}
return
errList
;
}
if
(
currentType
==
'
Array
'
)
{
if
(
type
==
'
Array
'
)
{
(
!
canUseObject
)
?
errList
.
push
(
`不能直接定义类型
${
type
}
,需要使用符合类型定义,请确认是否开启了可以直接定义 Array 类型参数;`
)
:
(
errList
=
[]);
}
else
{
if
(
types
[
type
])
{
// 数组元素的类型
let
itemType
=
types
[
type
][
0
];
for
(
let
i
=
0
;
i
<
value
.
length
;
i
++
)
{
let
subError
=
checkType
(
value
[
i
],
itemType
,
[]);
if
(
subError
&&
subError
.
length
)
{
errList
=
errList
.
concat
(
subError
)
}
}
}
else
{
errList
.
push
(
'
找不到定义的type [
'
+
type
+
'
]!
'
);
}
}
return
errList
;
}
if
(
currentType
==
'
Function
'
)
{
if
(
types
[
type
])
{
if
(
!
types
[
type
].
input
&&
!
types
[
type
].
output
)
{
errList
.
push
(
`找不到
${
types
[
type
]}
函数定义的输入输出`
);
}
}
else
{
errList
.
push
(
'
找不到定义的type [
'
+
type
+
'
]!
'
);
}
}
if
(
currentType
==
'
Promise
'
)
{
if
(
type
==
'
Promise
'
)
{
errList
=
[];
}
else
{
errList
.
push
(
`定义了
${
type
}
类型的参数,传入的却是
${
currentType
}
,请检查所传参数是否和接口定义的一致`
)
}
return
errList
;
}
if
(
currentType
==
'
Date
'
)
{
if
(
type
==
'
Date
'
)
{
errList
=
[];
}
else
{
errList
.
push
(
`定义了
${
type
}
类型的参数,传入的却是
${
currentType
}
,请检查所传参数是否和接口定义的一致`
)
}
return
errList
;
}
if
(
currentType
==
'
RegExp
'
)
{
if
(
type
==
'
RegExp
'
)
{
errList
=
[];
}
else
{
errList
.
push
(
`定义了
${
type
}
类型的参数,传入的却是
${
currentType
}
,请检查所传参数是否和接口定义的一致`
)
}
return
errList
;
}
return
errList
;
}
return
obj
;
}
/**
* 处理ast导出表达式
*
* @param {Object} ast ast
* @return {Object} ast
*/
const
handlExport
=
function
(
ast
)
{
traverse
[
"
default
"
](
ast
,
{
enter
(
path
)
{
if
(
path
.
node
.
type
===
'
ExportDefaultDeclaration
'
)
{
// 拿到export ddefault new Method(); 这一行代码
let
exportCode
=
generate
[
"
default
"
](
path
.
node
);
// 拿到 new Method(); 这一段代码
let
declarationCode
=
generate
[
"
default
"
](
path
.
node
.
declaration
);
// 得到 export default __OBJECT__WARPPER__(new Method());
let
codeSeg
=
exportCode
.
code
.
replace
(
declarationCode
.
code
,
'
__CML__WRAPPER__(
'
+
declarationCode
.
code
+
'
)
'
);
// 转成ast
let
replacement
=
parser
.
parse
(
codeSeg
,
{
plugins
:
parsePlugins
,
sourceType
:
'
module
'
});
traverse
[
"
default
"
].
removeProperties
(
replacement
);
// 替换
path
.
replaceWith
(
replacement
.
program
.
body
[
0
]);
path
.
stop
();
}
}
});
return
ast
;
};
/**
*
* @param {*} interfaceCode interface的代码
* @param {*} cmlCode cml的代码
* @param {*} interfacePath interface的文件路径
* @param {*} cmlPath cml的文件路径
* @param {*} cmlType web weex
* @param {*} enableTypes 启动的类型
*/
function
getCheckCode
(
interfaceCode
,
cmlCode
,
interfacePath
,
cmlPath
,
cmlType
,
enableTypes
)
{
let
interfaceDefines
=
getDefines
(
interfaceCode
,
interfacePath
).
defines
;
let
interfaceNumber
=
Object
.
keys
(
interfaceDefines
.
interfaces
).
length
;
if
(
interfaceNumber
===
0
)
{
throw
new
Error
(
`
${
interfacePath
}
中未定义interface`
)
}
else
if
(
interfaceNumber
>
1
)
{
throw
new
Error
(
`
${
interfacePath
}
中只能定义一个interface`
)
}
// 为了拿到expot 对象的class implements 的interface
let
cmlDefines
=
getDefines
(
cmlCode
,
cmlPath
);
const
newCode
=
generate
[
"
default
"
](
handlExport
(
cmlDefines
.
ast
)).
code
;
let
result
=
''
;
let
wrapperCode
=
''
;
if
(
interfacePath
)
{
interfacePath
=
path
.
resolve
(
interfacePath
);
interfacePath
=
cmlUtils
.
handleWinPath
(
interfacePath
);
result
+=
`const __INTERFACE__FILEPATH="
${
interfacePath
}
"`
;
}
if
(
cmlType
===
'
weex
'
)
{
function
throwError
(
content
)
{
var
modal
=
weex
.
requireModule
(
'
modal
'
)
modal
.
alert
({
message
:
`文件位置:
${
__INTERFACE__FILEPATH
}
${
content
}
`
})
}
result
+=
`
const __CML_ERROR__ =
${
throwError
.
toString
()}
`
}
else
{
function
throwError
(
content
)
{
throw
new
Error
(
`文件位置:
${
__INTERFACE__FILEPATH
}
${
content
}
`
)
}
result
+=
`
const __CML_ERROR__ =
${
throwError
.
toString
()}
`
}
wrapperCode
=
`
${
wrapper
.
toString
().
replace
(
/showErrorMessage/g
,
'
__CML_ERROR__
'
)}
`
result
+=
`
const __enableTypes__ =
${
JSON
.
stringify
(
enableTypes
)}
const __INTERFAE__DEFINES__ =
${
JSON
.
stringify
(
interfaceDefines
,
null
,
2
)}
;
const __CML__DEFINES__ =
${
JSON
.
stringify
(
cmlDefines
.
defines
,
null
,
2
)}
;
const __CML__WRAPPER__ =
${
wrapperCode
}
;
${
newCode
}
`
return
result
;
}
module
.
exports
=
{
getCheckCode
}
packages/mvvm-script-parser/package.json
已删除
100644 → 0
浏览文件 @
37b1a2db
{
"name"
:
"mvvm-script-parser"
,
"version"
:
"0.4.0-mvvm.2"
,
"description"
:
""
,
"main"
:
"index.js"
,
"scripts"
:
{
"test"
:
"echo
\"
Error: no test specified
\"
&& exit 1"
},
"author"
:
""
,
"license"
:
"ISC"
,
"dependencies"
:
{
"@babel/core"
:
"^7.3.4"
,
"@babel/generator"
:
"^7.4.0"
,
"@babel/parser"
:
"^7.3.4"
,
"@babel/traverse"
:
"^7.3.4"
,
"@babel/types"
:
"^7.3.4"
,
"chameleon-tool-utils"
:
"0.4.0-mvvm.2"
,
"mvvm-interface-parser"
:
"0.4.0-mvvm.2"
,
"runtime-check"
:
"0.4.0-mvvm.2"
}
}
\ No newline at end of file
packages/mvvm-script-parser/test/d.js
已删除
100644 → 0
浏览文件 @
37b1a2db
packages/mvvm-script-parser/test/dependencies.js
已删除
100644 → 0
浏览文件 @
37b1a2db
let
source
=
`import a from './a.js'
import {b,c} from './b.js'
import * as d from './c.js'
const e = require('./d.js');
require('./e.js')`
const
mvvmpack
=
require
(
'
../../mvvm-pack/index.js
'
);
const
path
=
require
(
'
path
'
);
let
compiler
=
new
mvvmpack
({
config
:
{
check
:
{
enable
:
true
,
// 是否开启接口校验
enableTypes
:
[]
// 接口校验支持的类型 可以开启["Object","Array","Nullable"]
}
},
logLevel
:
3
,
cmlType
:
'
web
'
,
media
:
'
dev
'
,
cmlRoot
:
path
.
resolve
(
'
./
'
),
projectRoot
:
path
.
resolve
(
__dirname
,
'
../
'
)
})
let
parser
=
require
(
'
../index.js
'
);
let
result
=
parser
.
JSCompile
({
source
,
compiler
,
realPath
:
path
.
join
(
__dirname
,
'
./dependencies.js
'
)})
packages/mvvm-script-parser/test/e.js
已删除
100644 → 0
浏览文件 @
37b1a2db
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录