react-magnetic-di
Version:
Context driven dependency injection
115 lines (104 loc) • 3.43 kB
JavaScript
;
var _require = require('../utils'),
getDiIdentifier = _require.getDiIdentifier,
getDiStatements = _require.getDiStatements,
getParentDiBlock = _require.getParentDiBlock,
getDiVars = _require.getDiVars;
module.exports = {
meta: {
type: 'suggestion',
docs: {
description: 'Disallow injecting dependencies not being used',
category: 'Possible Errors',
recommended: true
},
// fixable: 'code',
schema: [{
type: 'object',
properties: {
ignore: {
type: 'array',
items: {
type: 'string'
}
}
},
additionalProperties: false
}],
messages: {
extraneousInjectable: "Extraneous dependency: '{{name}}'. " + 'If it is not being used, remove it from the injectable list'
}
},
create: function create(context) {
var diIdentifier;
var blockReferences = new WeakMap();
var report = function report(node) {
return context.report({
node: node,
messageId: 'extraneousInjectable',
data: {
name: node.name
} // fix(fixer) {
// const lastArg = diStatement.expression.arguments.slice(-1)[0];
// return fixer.insertTextAfter(lastArg, `, ${node.name}`);
// },
});
};
return {
ImportDeclaration: function ImportDeclaration(node) {
if (!diIdentifier) diIdentifier = getDiIdentifier(node);
},
// this is to handle hooks and components recognised as used variables
// it does not cover JSX variables
BlockStatement: function BlockStatement(node) {
if (!diIdentifier) return;
var diStatements = getDiStatements(node, diIdentifier); // ignore locations where di was not explicitly set
if (!diStatements.length) return;
var diVars = getDiVars(diStatements);
blockReferences.set(node, {
di: diVars,
through: context.getScope().through.map(function (v) {
return v.identifier;
})
});
},
// as JSX elements are not treated as variables, for each JSX tag
// we check if there is a block with di() above and collect the tag as var
'JSXOpeningElement:exit': function JSXOpeningElementExit(node) {
if (!diIdentifier) return;
var varNode;
switch (node.name.type) {
case 'JSXIdentifier':
{
varNode = node.name;
break;
}
case 'JSXNamespacedName':
// TODO handle foo:Bar
return;
case 'JSXMemberExpression':
// TODO handle foo.Bar (but ignoring this.Bar)
return;
default:
return;
}
var parentBlock = getParentDiBlock(varNode, diIdentifier);
var blockVars = blockReferences.get(parentBlock);
if (!blockVars) return;
blockVars.through.push(varNode);
},
'BlockStatement:exit': function BlockStatementExit(node) {
if (!diIdentifier) return;
var blockVars = blockReferences.get(node);
if (!blockVars) return;
blockVars.di.forEach(function (varNode) {
var occurrences = blockVars.through.filter(function (v) {
return v.name === varNode.name;
});
if (occurrences.length > 1) return;
report(varNode);
});
}
};
}
};