123 lines
4.8 KiB
JavaScript
123 lines
4.8 KiB
JavaScript
/**
|
|
* disallow the deprecated directive replace property
|
|
*
|
|
* This rule disallows the replace attribute in a directive definition object.
|
|
* The replace property of a directive definition object is deprecated since angular 1.3 ([latest angular docs](https://docs.angularjs.org/api/ng/service/$compile).
|
|
*
|
|
* The option `ignoreReplaceFalse` let you ignore directive definitions with replace set to false.
|
|
*
|
|
* @version 0.15.0
|
|
* @category deprecatedAngularFeature
|
|
* @sinceAngularVersion 1.x
|
|
*/
|
|
'use strict';
|
|
|
|
var angularRule = require('./utils/angular-rule');
|
|
|
|
module.exports = {
|
|
meta: {
|
|
docs: {
|
|
url: 'https://github.com/Gillespie59/eslint-plugin-angular/blob/master/docs/rules/no-directive-replace.md'
|
|
},
|
|
schema: [{
|
|
type: 'object',
|
|
properties: {
|
|
ignoreReplaceFalse: {
|
|
type: 'boolean'
|
|
}
|
|
}
|
|
}]
|
|
},
|
|
create: angularRule(function(context) {
|
|
var options = context.options[0] || {};
|
|
var ignoreReplaceFalse = !!options.ignoreReplaceFalse;
|
|
|
|
var potentialReplaceNodes = {};
|
|
|
|
function addPotentialReplaceNode(variableName, node) {
|
|
var nodeList = potentialReplaceNodes[variableName] || [];
|
|
|
|
nodeList.push({
|
|
name: variableName,
|
|
node: node,
|
|
block: context.getScope().block.body
|
|
});
|
|
|
|
potentialReplaceNodes[variableName] = nodeList;
|
|
}
|
|
|
|
return {
|
|
'angular?directive': function(callExpressionNode, fnNode) {
|
|
if (!fnNode || !fnNode.body) {
|
|
return;
|
|
}
|
|
|
|
var body = fnNode.body.body ? fnNode.body.body : [fnNode.body];
|
|
|
|
body.forEach(function(statement) {
|
|
if (statement.type === 'ReturnStatement' || statement.type === 'ObjectExpression') {
|
|
// get potential replace node by argument name of empty string for object expressions
|
|
var potentialNodes = potentialReplaceNodes[''];
|
|
if (statement.argument) {
|
|
potentialNodes = potentialReplaceNodes[statement.argument.name || ''];
|
|
}
|
|
|
|
if (!potentialNodes) {
|
|
return;
|
|
}
|
|
potentialNodes.forEach(function(report) {
|
|
var block = statement.parent.type === 'ArrowFunctionExpression' ? statement : statement.parent;
|
|
|
|
// only reports nodes that belong to the same expression
|
|
if (report.block === block) {
|
|
context.report(report.node, 'Directive definition property replace is deprecated.');
|
|
}
|
|
});
|
|
}
|
|
});
|
|
},
|
|
AssignmentExpression: function(node) {
|
|
// Only check for literal member property assignments.
|
|
if (node.left.type !== 'MemberExpression') {
|
|
return;
|
|
}
|
|
// Only check setting properties named 'replace'.
|
|
if (node.left.property.name !== 'replace') {
|
|
return;
|
|
}
|
|
if (ignoreReplaceFalse && node.right.value === false) {
|
|
return;
|
|
}
|
|
addPotentialReplaceNode(node.left.object.name, node);
|
|
},
|
|
Property: function(node) {
|
|
// This only checks for objects which have defined a literal restrict property.
|
|
if (node.key.name !== 'replace') {
|
|
return;
|
|
}
|
|
if (ignoreReplaceFalse === true && node.value.value === false) {
|
|
return;
|
|
}
|
|
|
|
// assumption: Property always belongs to a ObjectExpression
|
|
var objectExpressionParent = node.parent.parent;
|
|
|
|
// add to potential replace nodes if the object is defined in a variable
|
|
if (objectExpressionParent.type === 'VariableDeclarator') {
|
|
addPotentialReplaceNode(objectExpressionParent.id.name, node);
|
|
}
|
|
|
|
// report directly if object is part of a return statement and inside a directive body
|
|
if (objectExpressionParent.type === 'ReturnStatement') {
|
|
addPotentialReplaceNode('', node);
|
|
}
|
|
|
|
// report directly if object is part of a arrow function and inside a directive body
|
|
if (objectExpressionParent.type === 'ArrowFunctionExpression') {
|
|
addPotentialReplaceNode('', node);
|
|
}
|
|
}
|
|
};
|
|
})
|
|
};
|