Skip to content

Commit 97011ec

Browse files
committed
fix: check imported get/getProperties/getWithDefault functions for missing dependencies in require-computed-property-dependencies rule
1 parent 7467c37 commit 97011ec

File tree

2 files changed

+79
-12
lines changed

2 files changed

+79
-12
lines changed

lib/rules/require-computed-property-dependencies.js

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,16 +117,16 @@ function parseComputedDependencies(args) {
117117
* or `this.get(…)`.
118118
*
119119
* @param {ASTNode} node
120-
* @param {string} importedEmberName
120+
* @param {object} importedNames
121121
* @returns {Array<ASTNode>}
122122
*/
123-
function findEmberGetCalls(node, importedEmberName) {
123+
function findEmberGetCalls(node, importedNames) {
124124
const results = [];
125125

126126
new Traverser().traverse(node, {
127127
enter(child) {
128128
if (types.isCallExpression(child)) {
129-
const dependency = extractEmberGetDependencies(child, importedEmberName);
129+
const dependency = extractEmberGetDependencies(child, importedNames);
130130

131131
if (dependency.length > 0) {
132132
results.push(child);
@@ -211,10 +211,13 @@ function getArrayOrRest(args) {
211211
* Extracts all static property keys used in the various forms of `Ember.get`.
212212
*
213213
* @param {ASTNode} call
214-
* @param {string} importedEmberName
214+
* @param {object} importedNames
215215
* @returns {Array<string>}
216216
*/
217-
function extractEmberGetDependencies(call, importedEmberName) {
217+
function extractEmberGetDependencies(
218+
call,
219+
{ importedEmberName, importedGetName, importedGetPropertiesName, importedGetWithDefaultName }
220+
) {
218221
if (
219222
isMemberExpression(call.callee, 'this', 'get') ||
220223
isMemberExpression(call.callee, 'this', 'getWithDefault')
@@ -226,7 +229,9 @@ function extractEmberGetDependencies(call, importedEmberName) {
226229
}
227230
} else if (
228231
isMemberExpression(call.callee, importedEmberName, 'get') ||
229-
isMemberExpression(call.callee, importedEmberName, 'getWithDefault')
232+
isMemberExpression(call.callee, importedEmberName, 'getWithDefault') ||
233+
isIdentifier(call.callee, importedGetName) ||
234+
isIdentifier(call.callee, importedGetWithDefaultName)
230235
) {
231236
const firstArg = call.arguments[0];
232237
const secondArgument = call.arguments[1];
@@ -238,7 +243,10 @@ function extractEmberGetDependencies(call, importedEmberName) {
238243
return getArrayOrRest(call.arguments)
239244
.filter(types.isStringLiteral)
240245
.map((arg) => arg.value);
241-
} else if (isMemberExpression(call.callee, importedEmberName, 'getProperties')) {
246+
} else if (
247+
isMemberExpression(call.callee, importedEmberName, 'getProperties') ||
248+
isIdentifier(call.callee, importedGetPropertiesName)
249+
) {
242250
const firstArg = call.arguments[0];
243251
const rest = call.arguments.slice(1);
244252

@@ -313,8 +321,11 @@ module.exports = {
313321

314322
let importedEmberName;
315323
let importedComputedName;
324+
let importedGetName;
325+
let importedGetPropertiesName;
326+
let importedGetWithDefaultName;
316327

317-
function checkComputedDependencies(node, nodeArguments, importedEmberName) {
328+
function checkComputedDependencies(node, nodeArguments, importedNames) {
318329
const declaredDependencies = parseComputedDependencies(nodeArguments);
319330

320331
if (!allowDynamicKeys) {
@@ -331,8 +342,8 @@ module.exports = {
331342
);
332343

333344
const usedKeys1 = javascriptUtils.flatMap(
334-
findEmberGetCalls(computedPropertyFunctionBody, importedEmberName),
335-
(node) => extractEmberGetDependencies(node, importedEmberName)
345+
findEmberGetCalls(computedPropertyFunctionBody, importedNames),
346+
(node) => extractEmberGetDependencies(node, importedNames)
336347
);
337348
const usedKeys2 = javascriptUtils.flatMap(
338349
findThisGetCalls(computedPropertyFunctionBody),
@@ -459,18 +470,35 @@ module.exports = {
459470
if (node.source.value === '@ember/object') {
460471
importedComputedName =
461472
importedComputedName || getImportIdentifier(node, '@ember/object', 'computed');
473+
importedGetName = importedGetName || getImportIdentifier(node, '@ember/object', 'get');
474+
importedGetPropertiesName =
475+
importedGetPropertiesName ||
476+
getImportIdentifier(node, '@ember/object', 'getProperties');
477+
importedGetWithDefaultName =
478+
importedGetWithDefaultName ||
479+
getImportIdentifier(node, '@ember/object', 'getWithDefault');
462480
}
463481
},
464482

465483
Identifier(node) {
466484
if (isEmberComputed(node, importedEmberName, importedComputedName)) {
467-
checkComputedDependencies(node, [], importedEmberName);
485+
checkComputedDependencies(node, [], {
486+
importedEmberName,
487+
importedGetName,
488+
importedGetPropertiesName,
489+
importedGetWithDefaultName,
490+
});
468491
}
469492
},
470493

471494
CallExpression(node) {
472495
if (isEmberComputed(node.callee, importedEmberName, importedComputedName)) {
473-
checkComputedDependencies(node, node.arguments, importedEmberName);
496+
checkComputedDependencies(node, node.arguments, {
497+
importedEmberName,
498+
importedGetName,
499+
importedGetPropertiesName,
500+
importedGetWithDefaultName,
501+
});
474502
}
475503
},
476504
};

tests/lib/rules/require-computed-property-dependencies.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,5 +1043,44 @@ ruleTester.run('require-computed-property-dependencies', rule, {
10431043
},
10441044
],
10451045
},
1046+
{
1047+
// Renamed get import:
1048+
code:
1049+
"import { computed, get as g } from '@ember/object'; computed(function() { return g(this, 'foo'); });",
1050+
output:
1051+
"import { computed, get as g } from '@ember/object'; computed('foo', function() { return g(this, 'foo'); });",
1052+
errors: [
1053+
{
1054+
message: 'Use of undeclared dependencies in computed property: foo',
1055+
type: 'CallExpression',
1056+
},
1057+
],
1058+
},
1059+
{
1060+
// Renamed getProperties import:
1061+
code:
1062+
"import { computed, getProperties as gp } from '@ember/object'; computed(function() { return gp(this, 'foo'); });",
1063+
output:
1064+
"import { computed, getProperties as gp } from '@ember/object'; computed('foo', function() { return gp(this, 'foo'); });",
1065+
errors: [
1066+
{
1067+
message: 'Use of undeclared dependencies in computed property: foo',
1068+
type: 'CallExpression',
1069+
},
1070+
],
1071+
},
1072+
{
1073+
// Renamed getWithDefault import:
1074+
code:
1075+
"import { computed, getWithDefault as gwd } from '@ember/object'; computed(function() { return gwd(this, 'foo', 'bar'); });",
1076+
output:
1077+
"import { computed, getWithDefault as gwd } from '@ember/object'; computed('foo', function() { return gwd(this, 'foo', 'bar'); });",
1078+
errors: [
1079+
{
1080+
message: 'Use of undeclared dependencies in computed property: foo',
1081+
type: 'CallExpression',
1082+
},
1083+
],
1084+
},
10461085
],
10471086
});

0 commit comments

Comments
 (0)