UNPKG

4.1 kBJavaScriptView Raw
1/**
2 * disallow the deprecated directive replace property
3 *
4 * This rule disallows the replace attribute in a directive definition object.
5 * 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).
6 *
7 * The option `ignoreReplaceFalse` let you ignore directive definitions with replace set to false.
8 *
9 * @version 0.15.0
10 * @category deprecatedAngularFeature
11 * @sinceAngularVersion 1.x
12 */
13'use strict';
14
15var angularRule = require('./utils/angular-rule');
16
17module.exports = {
18 meta: {
19 schema: [{
20 type: 'object',
21 properties: {
22 ignoreReplaceFalse: {
23 type: 'boolean'
24 }
25 }
26 }]
27 },
28 create: angularRule(function(context) {
29 var options = context.options[0] || {};
30 var ignoreReplaceFalse = !!options.ignoreReplaceFalse;
31
32 var potentialReplaceNodes = {};
33
34 function addPotentialReplaceNode(variableName, node) {
35 var nodeList = potentialReplaceNodes[variableName] || [];
36
37 nodeList.push({
38 name: variableName,
39 node: node,
40 block: context.getScope().block.body
41 });
42
43 potentialReplaceNodes[variableName] = nodeList;
44 }
45
46 return {
47 'angular?directive': function(callExpressionNode, fnNode) {
48 if (!fnNode || !fnNode.body) {
49 return;
50 }
51 fnNode.body.body.forEach(function(statement) {
52 if (statement.type === 'ReturnStatement') {
53 // get potential replace node by argument name of empty string for object expressions
54 var potentialNodes = potentialReplaceNodes[statement.argument.name || ''];
55 if (!potentialNodes) {
56 return;
57 }
58 potentialNodes.forEach(function(report) {
59 // only reports nodes that belong to the same expression
60 if (report.block === statement.parent) {
61 context.report(report.node, 'Directive definition property replace is deprecated.');
62 }
63 });
64 }
65 });
66 },
67 AssignmentExpression: function(node) {
68 // Only check for literal member property assignments.
69 if (node.left.type !== 'MemberExpression') {
70 return;
71 }
72 // Only check setting properties named 'replace'.
73 if (node.left.property.name !== 'replace') {
74 return;
75 }
76 if (ignoreReplaceFalse && node.right.value === false) {
77 return;
78 }
79 addPotentialReplaceNode(node.left.object.name, node);
80 },
81 Property: function(node) {
82 // This only checks for objects which have defined a literal restrict property.
83 if (node.key.name !== 'replace') {
84 return;
85 }
86 if (ignoreReplaceFalse === true && node.value.value === false) {
87 return;
88 }
89
90 // assumption: Property always belongs to a ObjectExpression
91 var objectExpressionParent = node.parent.parent;
92
93 // add to potential replace nodes if the object is defined in a variable
94 if (objectExpressionParent.type === 'VariableDeclarator') {
95 addPotentialReplaceNode(objectExpressionParent.id.name, node);
96 }
97
98 // report directly if object is part of a return statement and inside a directive body
99 if (objectExpressionParent.type === 'ReturnStatement') {
100 addPotentialReplaceNode('', node);
101 }
102 }
103 };
104 })
105};