Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitaf3700f

Browse files
authored
feat(no-ref-as-operand): useref.value to replaceref when emit (#2680)
1 parent827ab4b commitaf3700f

File tree

3 files changed

+521
-75
lines changed

3 files changed

+521
-75
lines changed

‎docs/rules/no-ref-as-operand.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ You must use `.value` to access the `Ref` value.
2525
import { ref } from 'vue'
2626
2727
export default {
28-
setup() {
28+
setup(_props, { emit }) {
2929
const count = ref(0)
3030
const ok = ref(true)
3131
@@ -34,12 +34,14 @@ export default {
3434
count.value + 1
3535
1 + count.value
3636
var msg = ok.value ? 'yes' : 'no'
37+
emit('increment', count.value)
3738
3839
/* ✗ BAD */
3940
count++
4041
count + 1
4142
1 + count
4243
var msg = ok ? 'yes' : 'no'
44+
emit('increment', count)
4345
4446
return {
4547
count

‎lib/rules/no-ref-as-operand.js

Lines changed: 248 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
'use strict'
66

7+
const{ findVariable}=require('@eslint-community/eslint-utils')
78
const{ extractRefObjectReferences}=require('../utils/ref-object-references')
89
constutils=require('../utils')
910

@@ -24,6 +25,40 @@ function isRefInit(data) {
2425
}
2526
returndata.defineChain.includes(/**@type {any} */(init))
2627
}
28+
29+
/**
30+
* Get the callee member node from the given CallExpression
31+
*@param {CallExpression} node CallExpression
32+
*/
33+
functiongetNameParamNode(node){
34+
constnameLiteralNode=node.arguments[0]
35+
if(nameLiteralNode&&utils.isStringLiteral(nameLiteralNode)){
36+
constname=utils.getStringLiteralValue(nameLiteralNode)
37+
if(name!=null){
38+
return{ name,loc:nameLiteralNode.loc}
39+
}
40+
}
41+
42+
// cannot check
43+
returnnull
44+
}
45+
46+
/**
47+
* Get the callee member node from the given CallExpression
48+
*@param {CallExpression} node CallExpression
49+
*/
50+
functiongetCalleeMemberNode(node){
51+
constcallee=utils.skipChainExpression(node.callee)
52+
53+
if(callee.type==='MemberExpression'){
54+
constname=utils.getStaticPropertyName(callee)
55+
if(name){
56+
return{ name,member:callee}
57+
}
58+
}
59+
returnnull
60+
}
61+
2762
module.exports={
2863
meta:{
2964
type:'suggestion',
@@ -44,6 +79,22 @@ module.exports = {
4479
create(context){
4580
/**@type {RefObjectReferences} */
4681
letrefReferences
82+
constsetupContexts=newMap()
83+
84+
/**
85+
* Collect identifier id
86+
*@param {Identifier} node
87+
*@param {Set<Identifier>} referenceIds
88+
*/
89+
functioncollectReferenceIds(node,referenceIds){
90+
constvariable=findVariable(utils.getScope(context,node),node)
91+
if(!variable){
92+
return
93+
}
94+
for(constreferenceofvariable.references){
95+
referenceIds.add(reference.identifier)
96+
}
97+
}
4798

4899
/**
49100
*@param {Identifier} node
@@ -64,90 +115,213 @@ module.exports = {
64115
}
65116
})
66117
}
67-
return{
68-
Program(){
69-
refReferences=extractRefObjectReferences(context)
70-
},
71-
// if (refValue)
72-
/**@param {Identifier} node */
73-
'IfStatement>Identifier'(node){
74-
reportIfRefWrapped(node)
75-
},
76-
// switch (refValue)
77-
/**@param {Identifier} node */
78-
'SwitchStatement>Identifier'(node){
79-
reportIfRefWrapped(node)
80-
},
81-
// -refValue, +refValue, !refValue, ~refValue, typeof refValue
82-
/**@param {Identifier} node */
83-
'UnaryExpression>Identifier'(node){
84-
reportIfRefWrapped(node)
85-
},
86-
// refValue++, refValue--
87-
/**@param {Identifier} node */
88-
'UpdateExpression>Identifier'(node){
89-
reportIfRefWrapped(node)
90-
},
91-
// refValue+1, refValue-1
92-
/**@param {Identifier} node */
93-
'BinaryExpression>Identifier'(node){
118+
119+
/**
120+
*@param {CallExpression} node
121+
*/
122+
functionreportWrappedIdentifiers(node){
123+
constnodes=node.arguments.filter((node)=>node.type==='Identifier')
124+
for(constnodeofnodes){
94125
reportIfRefWrapped(node)
95-
},
96-
// refValue+=1, refValue-=1, foo+=refValue, foo-=refValue
97-
/**@param {Identifier & {parent: AssignmentExpression}} node */
98-
'AssignmentExpression>Identifier'(node){
99-
if(node.parent.operator==='='&&node.parent.left!==node){
126+
}
127+
}
128+
129+
constprogramNode=context.getSourceCode().ast
130+
131+
constcallVisitor={
132+
/**
133+
*@param {CallExpression} node
134+
*@param {import('../utils').VueObjectData} [info]
135+
*/
136+
CallExpression(node,info){
137+
constnameWithLoc=getNameParamNode(node)
138+
if(!nameWithLoc){
139+
// cannot check
100140
return
101141
}
102-
reportIfRefWrapped(node)
103-
},
104-
// refValue || other, refValue && other. ignore: other || refValue
105-
/**@param {Identifier & {parent: LogicalExpression}} node */
106-
'LogicalExpression>Identifier'(node){
107-
if(node.parent.left!==node){
142+
143+
// verify setup context
144+
constsetupContext=setupContexts.get(info ?info.node :programNode)
145+
if(!setupContext){
108146
return
109147
}
110-
// Report only constants.
111-
constdata=refReferences.get(node)
148+
149+
const{ contextReferenceIds, emitReferenceIds}=setupContext
112150
if(
113-
!data||
114-
!data.variableDeclaration||
115-
data.variableDeclaration.kind!=='const'
151+
node.callee.type==='Identifier'&&
152+
emitReferenceIds.has(node.callee)
116153
){
117-
return
154+
// verify setup(props,{emit}) {emit()}
155+
reportWrappedIdentifiers(node)
156+
}else{
157+
constemit=getCalleeMemberNode(node)
158+
if(
159+
emit&&
160+
emit.name==='emit'&&
161+
emit.member.object.type==='Identifier'&&
162+
contextReferenceIds.has(emit.member.object)
163+
){
164+
// verify setup(props,context) {context.emit()}
165+
reportWrappedIdentifiers(node)
166+
}
118167
}
119-
reportIfRefWrapped(node)
120-
},
121-
// refValue ? x : y
122-
/**@param {Identifier & {parent: ConditionalExpression}} node */
123-
'ConditionalExpression>Identifier'(node){
124-
if(node.parent.test!==node){
125-
return
168+
}
169+
}
170+
171+
returnutils.compositingVisitors(
172+
{
173+
Program(){
174+
refReferences=extractRefObjectReferences(context)
175+
},
176+
// if (refValue)
177+
/**@param {Identifier} node */
178+
'IfStatement>Identifier'(node){
179+
reportIfRefWrapped(node)
180+
},
181+
// switch (refValue)
182+
/**@param {Identifier} node */
183+
'SwitchStatement>Identifier'(node){
184+
reportIfRefWrapped(node)
185+
},
186+
// -refValue, +refValue, !refValue, ~refValue, typeof refValue
187+
/**@param {Identifier} node */
188+
'UnaryExpression>Identifier'(node){
189+
reportIfRefWrapped(node)
190+
},
191+
// refValue++, refValue--
192+
/**@param {Identifier} node */
193+
'UpdateExpression>Identifier'(node){
194+
reportIfRefWrapped(node)
195+
},
196+
// refValue+1, refValue-1
197+
/**@param {Identifier} node */
198+
'BinaryExpression>Identifier'(node){
199+
reportIfRefWrapped(node)
200+
},
201+
// refValue+=1, refValue-=1, foo+=refValue, foo-=refValue
202+
/**@param {Identifier & {parent: AssignmentExpression}} node */
203+
'AssignmentExpression>Identifier'(node){
204+
if(node.parent.operator==='='&&node.parent.left!==node){
205+
return
206+
}
207+
reportIfRefWrapped(node)
208+
},
209+
// refValue || other, refValue && other. ignore: other || refValue
210+
/**@param {Identifier & {parent: LogicalExpression}} node */
211+
'LogicalExpression>Identifier'(node){
212+
if(node.parent.left!==node){
213+
return
214+
}
215+
// Report only constants.
216+
constdata=refReferences.get(node)
217+
if(
218+
!data||
219+
!data.variableDeclaration||
220+
data.variableDeclaration.kind!=='const'
221+
){
222+
return
223+
}
224+
reportIfRefWrapped(node)
225+
},
226+
// refValue ? x : y
227+
/**@param {Identifier & {parent: ConditionalExpression}} node */
228+
'ConditionalExpression>Identifier'(node){
229+
if(node.parent.test!==node){
230+
return
231+
}
232+
reportIfRefWrapped(node)
233+
},
234+
// `${refValue}`
235+
/**@param {Identifier} node */
236+
'TemplateLiteral>Identifier'(node){
237+
reportIfRefWrapped(node)
238+
},
239+
// refValue.x
240+
/**@param {Identifier & {parent: MemberExpression}} node */
241+
'MemberExpression>Identifier'(node){
242+
if(node.parent.object!==node){
243+
return
244+
}
245+
constname=utils.getStaticPropertyName(node.parent)
246+
if(
247+
name==='value'||
248+
name==null||
249+
// WritableComputedRef
250+
name==='effect'
251+
){
252+
return
253+
}
254+
reportIfRefWrapped(node)
126255
}
127-
reportIfRefWrapped(node)
128256
},
129-
// `${refValue}`
130-
/**@param {Identifier} node */
131-
'TemplateLiteral>Identifier'(node){
132-
reportIfRefWrapped(node)
133-
},
134-
// refValue.x
135-
/**@param {Identifier & {parent: MemberExpression}} node */
136-
'MemberExpression>Identifier'(node){
137-
if(node.parent.object!==node){
138-
return
139-
}
140-
constname=utils.getStaticPropertyName(node.parent)
141-
if(
142-
name==='value'||
143-
name==null||
144-
// WritableComputedRef
145-
name==='effect'
146-
){
147-
return
257+
utils.defineScriptSetupVisitor(context,{
258+
onDefineEmitsEnter(node){
259+
if(
260+
!node.parent||
261+
node.parent.type!=='VariableDeclarator'||
262+
node.parent.init!==node
263+
){
264+
return
265+
}
266+
267+
constemitParam=node.parent.id
268+
if(emitParam.type!=='Identifier'){
269+
return
270+
}
271+
272+
// const emit = defineEmits()
273+
constemitReferenceIds=newSet()
274+
collectReferenceIds(emitParam,emitReferenceIds)
275+
276+
setupContexts.set(programNode,{
277+
contextReferenceIds:newSet(),
278+
emitReferenceIds
279+
})
280+
},
281+
...callVisitor
282+
}),
283+
utils.defineVueVisitor(context,{
284+
onSetupFunctionEnter(node,{node:vueNode}){
285+
constcontextParam=utils.skipDefaultParamValue(node.params[1])
286+
if(!contextParam){
287+
// no arguments
288+
return
289+
}
290+
if(
291+
contextParam.type==='RestElement'||
292+
contextParam.type==='ArrayPattern'
293+
){
294+
// cannot check
295+
return
296+
}
297+
298+
constcontextReferenceIds=newSet()
299+
constemitReferenceIds=newSet()
300+
if(contextParam.type==='ObjectPattern'){
301+
constemitProperty=utils.findAssignmentProperty(
302+
contextParam,
303+
'emit'
304+
)
305+
if(!emitProperty||emitProperty.value.type!=='Identifier'){
306+
return
307+
}
308+
309+
// `setup(props, {emit})`
310+
collectReferenceIds(emitProperty.value,emitReferenceIds)
311+
}else{
312+
// `setup(props, context)`
313+
collectReferenceIds(contextParam,contextReferenceIds)
314+
}
315+
setupContexts.set(vueNode,{
316+
contextReferenceIds,
317+
emitReferenceIds
318+
})
319+
},
320+
...callVisitor,
321+
onVueObjectExit(node){
322+
setupContexts.delete(node)
148323
}
149-
reportIfRefWrapped(node)
150-
}
151-
}
324+
})
325+
)
152326
}
153327
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp