Skip to content

Commit 67ce653

Browse files
committed
make ignoreAssignmentVariable recursive
1 parent 8980e28 commit 67ce653

File tree

2 files changed

+39
-18
lines changed

2 files changed

+39
-18
lines changed

__tests__/always-return.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,11 @@ ruleTester.run('always-return', rule, {
106106
options: [{ ignoreLastCallback: true }],
107107
},
108108
`hey.then(x => { window.a = x })`,
109+
`hey.then(x => { window.a.n = x })`,
110+
`hey.then(x => { window[12] = x })`,
111+
`hey.then(x => { window[12]["test"] = x })`,
109112
{
110-
code: `hey.then(x => { window.a.x = x })`,
113+
code: `hey.then(x => { window.a.x.y = x })`,
111114
options: [{ ignoreAssignmentVariable: ['window.a'] }],
112115
},
113116
{
@@ -255,17 +258,12 @@ ruleTester.run('always-return', rule, {
255258
},
256259
{
257260
code: `hey.then(x => { ++window.a })`,
258-
options: [{ ignoreAssignmentVariable: ['window.a'] }],
259-
errors: [{ message }],
260-
},
261-
{
262-
code: `hey.then(x => { window.a.b.c = x })`,
263-
options: [{ ignoreAssignmentVariable: ['window.a'] }],
261+
options: [{ ignoreAssignmentVariable: ['window', 'window.a'] }],
264262
errors: [{ message }],
265263
},
266264
{
267265
code: `hey.then(x => { let a = x })`,
268-
options: [{ ignoreAssignmentVariable: ['window.a'] }],
266+
options: [{ ignoreAssignmentVariable: ['window'] }],
269267
errors: [{ message }],
270268
},
271269
],

rules/always-return.js

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,36 @@ function peek(arr) {
124124
return arr[arr.length - 1]
125125
}
126126

127+
/**
128+
* Gets the full object name for a MemberExpression or Identifier
129+
* @param {import('estree').MemberExpression | import('estree').Identifier} node
130+
* @returns {string}
131+
*/
132+
function getFullObjectName(node) {
133+
if (node.type === 'Identifier') {
134+
return node.name
135+
}
136+
const objectName = getFullObjectName(node.object)
137+
const propertyName = node.property.name
138+
return `${objectName}${node.computed ? '[' : '.'}${propertyName}${node.computed ? ']' : ''}`
139+
}
140+
141+
/**
142+
* Checks if the given name starts with an ignored variable
143+
* @param {string} name
144+
* @param {string[]} ignoredVars
145+
* @returns {boolean}
146+
*/
147+
function startsWithIgnoredVar(name, ignoredVars) {
148+
return ignoredVars.some(
149+
(ignoredVar) =>
150+
name === ignoredVar ||
151+
(name.startsWith(ignoredVar) &&
152+
(name.charAt(ignoredVar.length) === '.' ||
153+
name.charAt(ignoredVar.length) === '[')),
154+
)
155+
}
156+
127157
/**
128158
* Checks if the node is an assignment to an ignored variable
129159
* @param {Node} node
@@ -137,17 +167,10 @@ function isIgnoredAssignment(node, ignoredVars) {
137167
const left = expr.left
138168
// istanbul ignore else
139169
if (left.type === 'MemberExpression') {
140-
if (left.object.type === 'Identifier') {
141-
return ignoredVars.includes(left.object.name)
142-
}
143-
if (
144-
left.object.type === 'MemberExpression' &&
145-
left.object.object.type === 'Identifier'
146-
) {
147-
const fullName = `${left.object.object.name}.${left.object.property.name}`
148-
return ignoredVars.includes(fullName)
149-
}
170+
const fullName = getFullObjectName(left.object)
171+
return startsWithIgnoredVar(fullName, ignoredVars)
150172
}
173+
// istanbul ignore next
151174
// fallback
152175
return false
153176
}

0 commit comments

Comments
 (0)