提交 1f1229dd 编写于 作者: fxy060608's avatar fxy060608

fix(cli): output resource path for compiler errors #604

上级 535a3610
...@@ -584,7 +584,12 @@ describe('mp:compiler-extra', () => { ...@@ -584,7 +584,12 @@ describe('mp:compiler-extra', () => {
`<view data-test="{{'hello'+aaa}}"></view>` `<view data-test="{{'hello'+aaa}}"></view>`
) )
}) })
it('generate event ', () => { it('generate event ', () => {
assertCodegen(
`<view @/>`,
`<view></view>`
)
assertCodegen( assertCodegen(
`<text v-for="item in items['metas']" :key="item['id']" class="title" @tap="handle(item['id'],item['title'])">{{item.title}}</text>`, `<text v-for="item in items['metas']" :key="item['id']" class="title" @tap="handle(item['id'],item['title'])">{{item.title}}</text>`,
`<block wx:for="{{items['metas']}}" wx:for-item="item" wx:for-index="__i0__" wx:key="id"><text data-event-opts="{{[['tap',[['handle',['$0','$1'],[[['items.metas','id',item['id'],'id']],[['items.metas','id',item['id'],'title']]]]]]]}}" class="title" bindtap="__e">{{item.title}}</text></block>` `<block wx:for="{{items['metas']}}" wx:for-item="item" wx:for-index="__i0__" wx:key="id"><text data-event-opts="{{[['tap',[['handle',['$0','$1'],[[['items.metas','id',item['id'],'id']],[['items.metas','id',item['id'],'title']]]]]]]}}" class="title" bindtap="__e">{{item.title}}</text></block>`
......
...@@ -2,7 +2,7 @@ const compiler = require('../lib') ...@@ -2,7 +2,7 @@ const compiler = require('../lib')
const res = compiler.compile( const res = compiler.compile(
` `
<view v-for="item in dataList" :key="item.id" @click="click1(item, 1);click2(item, 2);"/> <view @/>
`, { `, {
resourcePath: '/User/fxy/Documents/test.wxml', resourcePath: '/User/fxy/Documents/test.wxml',
mp: { mp: {
......
...@@ -55,10 +55,18 @@ module.exports = { ...@@ -55,10 +55,18 @@ module.exports = {
} }
// console.log(`function render(){${res.render}}`) // console.log(`function render(){${res.render}}`)
const ast = parser.parse(`function render(){${res.render}}`) const ast = parser.parse(`function render(){${res.render}}`)
let template = ''
res.render = generateScript(traverseScript(ast, state), state)
try {
let template = generateTemplate(traverseTemplate(ast, state), state) res.render = generateScript(traverseScript(ast, state), state)
template = generateTemplate(traverseTemplate(ast, state), state)
} catch (e) {
console.error(e)
throw new Error('Compile failed at ' + options.resourcePath.replace(
path.extname(options.resourcePath),
'.vue'
))
}
res.specialMethods = state.options.specialMethods || new Set() res.specialMethods = state.options.specialMethods || new Set()
delete state.options.specialMethods delete state.options.specialMethods
......
...@@ -167,7 +167,7 @@ function getMethodName (methodName) { ...@@ -167,7 +167,7 @@ function getMethodName (methodName) {
return methodName === '__HOLDER__' ? '' : methodName return methodName === '__HOLDER__' ? '' : methodName
} }
function parseEventByCallExpression (callExpr, methods) { function parseEventByCallExpression (callExpr, methods) {
let methodName = callExpr.callee.name let methodName = callExpr.callee.name
if (methodName === '$set') { if (methodName === '$set') {
methodName = INTERNAL_SET_SYNC methodName = INTERNAL_SET_SYNC
...@@ -197,12 +197,12 @@ function parseEventByCallExpression (callExpr, methods) { ...@@ -197,12 +197,12 @@ function parseEventByCallExpression (callExpr, methods) {
arrayExpression.push(t.arrayExpression(argsExpression)) arrayExpression.push(t.arrayExpression(argsExpression))
} }
} }
methods.push(t.arrayExpression(arrayExpression)) methods.push(t.arrayExpression(arrayExpression))
} }
function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false, tagName, ret) { function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false, tagName, ret) {
const key = keyPath.node const key = keyPath.node
let type = key.value || key.name let type = key.value || key.name || ''
const isCustom = isComponent && !isNativeOn const isCustom = isComponent && !isNativeOn
...@@ -211,124 +211,126 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false, ...@@ -211,124 +211,126 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
let isPassive = false let isPassive = false
let isOnce = false let isOnce = false
isPassive = type.charAt(0) === VUE_EVENT_MODIFIERS.passive let methods = []
type = isPassive ? type.slice(1) : type
isOnce = type.charAt(0) === VUE_EVENT_MODIFIERS.once // Prefixed last, checked first if (type) {
type = isOnce ? type.slice(1) : type isPassive = type.charAt(0) === VUE_EVENT_MODIFIERS.passive
type = isPassive ? type.slice(1) : type
isCapture = type.charAt(0) === VUE_EVENT_MODIFIERS.capture isOnce = type.charAt(0) === VUE_EVENT_MODIFIERS.once // Prefixed last, checked first
type = isCapture ? type.slice(1) : type type = isOnce ? type.slice(1) : type
const specialEvents = state.options.platform.specialEvents isCapture = type.charAt(0) === VUE_EVENT_MODIFIERS.capture
const isSpecialEvent = specialEvents[tagName] && Object.keys(specialEvents[tagName]).includes(type) type = isCapture ? type.slice(1) : type
let methods = [] const specialEvents = state.options.platform.specialEvents
const isSpecialEvent = specialEvents[tagName] && Object.keys(specialEvents[tagName]).includes(type)
if (!valuePath.isArrayExpression()) { if (!valuePath.isArrayExpression()) {
valuePath = [valuePath] valuePath = [valuePath]
} else { } else {
valuePath = valuePath.get('elements') valuePath = valuePath.get('elements')
} }
valuePath.forEach(funcPath => { valuePath.forEach(funcPath => {
if ( // wxs event if ( // wxs event
funcPath.isMemberExpression() && funcPath.isMemberExpression() &&
t.isIdentifier(funcPath.node.object) && t.isIdentifier(funcPath.node.object) &&
state.options.filterModules.includes(funcPath.node.object.name) state.options.filterModules.includes(funcPath.node.object.name)
) { ) {
const { const {
getEventType, getEventType,
formatEventType formatEventType
} = state.options.platform } = state.options.platform
const wxsEventType = formatEventType(getEventType(type)) const wxsEventType = formatEventType(getEventType(type))
if (key.value) { if (key.value) {
key.value = wxsEventType key.value = wxsEventType
} else { } else {
key.name = wxsEventType key.name = wxsEventType
}
} else if (funcPath.isIdentifier()) { // on:{click:handle}
if (!isSpecialEvent) {
const arrayExpression = [t.stringLiteral(getMethodName(funcPath.node.name))]
if (!isCustom) { // native events
arrayExpression.push(defaultArgs)
} }
methods.push(t.arrayExpression(arrayExpression)) } else if (funcPath.isIdentifier()) { // on:{click:handle}
} else { if (!isSpecialEvent) {
if (!state.options.specialMethods) { const arrayExpression = [t.stringLiteral(getMethodName(funcPath.node.name))]
state.options.specialMethods = new Set() if (!isCustom) { // native events
arrayExpression.push(defaultArgs)
}
methods.push(t.arrayExpression(arrayExpression))
} else {
if (!state.options.specialMethods) {
state.options.specialMethods = new Set()
}
state.options.specialMethods.add(funcPath.node.name)
} }
state.options.specialMethods.add(funcPath.node.name) } else if (isSpecialEvent) {
} state.errors.add(
} else if (isSpecialEvent) { `${tagName} 组件 ${type} 事件仅支持 @${type}="methodName" 方式绑定`
state.errors.add( )
`${tagName} 组件 ${type} 事件仅支持 @${type}="methodName" 方式绑定` } else if (funcPath.isArrowFunctionExpression()) { // e=>count++
) methods.push(addEventExpressionStatement(funcPath, state, isCustom))
} else if (funcPath.isArrowFunctionExpression()) { // e=>count++ } else {
methods.push(addEventExpressionStatement(funcPath, state, isCustom)) let anonymous = true
} else {
let anonymous = true
// "click":function($event) {click1(item);click2(item);} // "click":function($event) {click1(item);click2(item);}
const body = funcPath.node.body.body const body = funcPath.node.body.body
if (body.length) { if (body.length) {
const exprStatements = body.filter(node => { const exprStatements = body.filter(node => {
return t.isExpressionStatement(node) && t.isCallExpression(node.expression) return t.isExpressionStatement(node) && t.isCallExpression(node.expression)
})
if (exprStatements.length === body.length) {
anonymous = false
exprStatements.forEach(exprStatement => {
parseEventByCallExpression(exprStatement.expression, methods)
}) })
} if (exprStatements.length === body.length) {
}
anonymous && funcPath.traverse({
noScope: true,
MemberExpression (path) {
if (path.node.object.name === '$event' && path.node.property.name ===
'stopPropagation') {
isCatch = true
path.stop()
}
},
AssignmentExpression (path) { // "update:title": function($event) {title = $event}
const left = path.node.left
const right = path.node.right
// v-bind:title.sync="title"
if (t.isIdentifier(left) &&
t.isIdentifier(right) &&
right.name === '$event' &&
type.indexOf('update:') === 0) {
methods.push(t.arrayExpression( // ['$set',['title','$event']]
[
t.stringLiteral(INTERNAL_SET_SYNC),
t.arrayExpression([
t.identifier(left.name),
t.stringLiteral(left.name),
t.stringLiteral('$event')
])
]
))
anonymous = false anonymous = false
path.stop() exprStatements.forEach(exprStatement => {
parseEventByCallExpression(exprStatement.expression, methods)
})
} }
}, }
ReturnStatement (path) {
const argument = path.node.argument anonymous && funcPath.traverse({
if (t.isCallExpression(argument)) { noScope: true,
if (t.isIdentifier(argument.callee)) { MemberExpression (path) {
if (path.node.object.name === '$event' && path.node.property.name ===
'stopPropagation') {
isCatch = true
path.stop()
}
},
AssignmentExpression (path) { // "update:title": function($event) {title = $event}
const left = path.node.left
const right = path.node.right
// v-bind:title.sync="title"
if (t.isIdentifier(left) &&
t.isIdentifier(right) &&
right.name === '$event' &&
type.indexOf('update:') === 0) {
methods.push(t.arrayExpression( // ['$set',['title','$event']]
[
t.stringLiteral(INTERNAL_SET_SYNC),
t.arrayExpression([
t.identifier(left.name),
t.stringLiteral(left.name),
t.stringLiteral('$event')
])
]
))
anonymous = false anonymous = false
parseEventByCallExpression(argument, methods) path.stop()
}
},
ReturnStatement (path) {
const argument = path.node.argument
if (t.isCallExpression(argument)) {
if (t.isIdentifier(argument.callee)) {
anonymous = false
parseEventByCallExpression(argument, methods)
}
} }
} }
})
if (anonymous) {
methods.push(addEventExpressionStatement(funcPath, state, isComponent, isNativeOn))
} }
})
if (anonymous) {
methods.push(addEventExpressionStatement(funcPath, state, isComponent, isNativeOn))
} }
} })
}) }
return { return {
type, type,
...@@ -345,6 +347,10 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false, ...@@ -345,6 +347,10 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
function _processEvent (path, state, isComponent, isNativeOn = false, tagName, ret) { function _processEvent (path, state, isComponent, isNativeOn = false, tagName, ret) {
const opts = [] const opts = []
// remove invalid event
path.node.value.properties = path.node.value.properties.filter(property => {
return property.key.value || property.key.name
})
const len = path.node.value.properties.length const len = path.node.value.properties.length
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
const propertyPath = path.get(`value.properties.${i}`) const propertyPath = path.get(`value.properties.${i}`)
...@@ -439,4 +445,4 @@ module.exports = function processEvent (paths, path, state, isComponent, tagName ...@@ -439,4 +445,4 @@ module.exports = function processEvent (paths, path, state, isComponent, tagName
) )
return ret return ret
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册