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

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

上级 535a3610
......@@ -584,7 +584,12 @@ describe('mp:compiler-extra', () => {
`<view data-test="{{'hello'+aaa}}"></view>`
)
})
it('generate event ', () => {
it('generate event ', () => {
assertCodegen(
`<view @/>`,
`<view></view>`
)
assertCodegen(
`<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>`
......
......@@ -2,7 +2,7 @@ const compiler = require('../lib')
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',
mp: {
......
......@@ -55,10 +55,18 @@ module.exports = {
}
// console.log(`function render(){${res.render}}`)
const ast = parser.parse(`function render(){${res.render}}`)
res.render = generateScript(traverseScript(ast, state), state)
let template = generateTemplate(traverseTemplate(ast, state), state)
let template = ''
try {
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()
delete state.options.specialMethods
......
......@@ -167,7 +167,7 @@ function getMethodName (methodName) {
return methodName === '__HOLDER__' ? '' : methodName
}
function parseEventByCallExpression (callExpr, methods) {
function parseEventByCallExpression (callExpr, methods) {
let methodName = callExpr.callee.name
if (methodName === '$set') {
methodName = INTERNAL_SET_SYNC
......@@ -197,12 +197,12 @@ function parseEventByCallExpression (callExpr, methods) {
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) {
const key = keyPath.node
let type = key.value || key.name
let type = key.value || key.name || ''
const isCustom = isComponent && !isNativeOn
......@@ -211,124 +211,126 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
let isPassive = false
let isOnce = false
isPassive = type.charAt(0) === VUE_EVENT_MODIFIERS.passive
type = isPassive ? type.slice(1) : type
let methods = []
isOnce = type.charAt(0) === VUE_EVENT_MODIFIERS.once // Prefixed last, checked first
type = isOnce ? type.slice(1) : type
if (type) {
isPassive = type.charAt(0) === VUE_EVENT_MODIFIERS.passive
type = isPassive ? type.slice(1) : type
isCapture = type.charAt(0) === VUE_EVENT_MODIFIERS.capture
type = isCapture ? type.slice(1) : type
isOnce = type.charAt(0) === VUE_EVENT_MODIFIERS.once // Prefixed last, checked first
type = isOnce ? type.slice(1) : type
const specialEvents = state.options.platform.specialEvents
const isSpecialEvent = specialEvents[tagName] && Object.keys(specialEvents[tagName]).includes(type)
isCapture = type.charAt(0) === VUE_EVENT_MODIFIERS.capture
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()) {
valuePath = [valuePath]
} else {
valuePath = valuePath.get('elements')
}
if (!valuePath.isArrayExpression()) {
valuePath = [valuePath]
} else {
valuePath = valuePath.get('elements')
}
valuePath.forEach(funcPath => {
if ( // wxs event
funcPath.isMemberExpression() &&
t.isIdentifier(funcPath.node.object) &&
state.options.filterModules.includes(funcPath.node.object.name)
) {
const {
getEventType,
formatEventType
} = state.options.platform
const wxsEventType = formatEventType(getEventType(type))
if (key.value) {
key.value = wxsEventType
} else {
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)
valuePath.forEach(funcPath => {
if ( // wxs event
funcPath.isMemberExpression() &&
t.isIdentifier(funcPath.node.object) &&
state.options.filterModules.includes(funcPath.node.object.name)
) {
const {
getEventType,
formatEventType
} = state.options.platform
const wxsEventType = formatEventType(getEventType(type))
if (key.value) {
key.value = wxsEventType
} else {
key.name = wxsEventType
}
methods.push(t.arrayExpression(arrayExpression))
} else {
if (!state.options.specialMethods) {
state.options.specialMethods = new Set()
} 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 (!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(
`${tagName} 组件 ${type} 事件仅支持 @${type}="methodName" 方式绑定`
)
} else if (funcPath.isArrowFunctionExpression()) { // e=>count++
methods.push(addEventExpressionStatement(funcPath, state, isCustom))
} else {
let anonymous = true
} else if (isSpecialEvent) {
state.errors.add(
`${tagName} 组件 ${type} 事件仅支持 @${type}="methodName" 方式绑定`
)
} else if (funcPath.isArrowFunctionExpression()) { // e=>count++
methods.push(addEventExpressionStatement(funcPath, state, isCustom))
} else {
let anonymous = true
// "click":function($event) {click1(item);click2(item);}
const body = funcPath.node.body.body
if (body.length) {
const exprStatements = body.filter(node => {
return t.isExpressionStatement(node) && t.isCallExpression(node.expression)
})
if (exprStatements.length === body.length) {
anonymous = false
exprStatements.forEach(exprStatement => {
parseEventByCallExpression(exprStatement.expression, methods)
// "click":function($event) {click1(item);click2(item);}
const body = funcPath.node.body.body
if (body.length) {
const exprStatements = body.filter(node => {
return t.isExpressionStatement(node) && t.isCallExpression(node.expression)
})
}
}
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')
])
]
))
if (exprStatements.length === body.length) {
anonymous = false
path.stop()
exprStatements.forEach(exprStatement => {
parseEventByCallExpression(exprStatement.expression, methods)
})
}
},
ReturnStatement (path) {
const argument = path.node.argument
if (t.isCallExpression(argument)) {
if (t.isIdentifier(argument.callee)) {
}
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
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 {
type,
......@@ -345,6 +347,10 @@ function parseEvent (keyPath, valuePath, state, isComponent, isNativeOn = false,
function _processEvent (path, state, isComponent, isNativeOn = false, tagName, ret) {
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
for (let i = 0; i < len; i++) {
const propertyPath = path.get(`value.properties.${i}`)
......@@ -439,4 +445,4 @@ module.exports = function processEvent (paths, path, state, isComponent, tagName
)
return ret
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册