all files / eslint-plugin-angular/rules/ no-directive-replace.js

100% Statements 37/37
100% Branches 34/34
100% Functions 7/7
100% Lines 37/37
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102                            27× 27×   27×   10×   10×           10×     27×   18×   16× 33×   15× 15×                                 11×                                            
/**
 * 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
 */
'use strict';
 
var angularRule = require('./utils/angular-rule');
 
module.exports = 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;
            }
            fnNode.body.body.forEach(function(statement) {
                if (statement.type === 'ReturnStatement') {
                    // get potential replace node by argument name of empty string for object expressions
                    var potentialNodes = potentialReplaceNodes[statement.argument.name || ''];
                    if (!potentialNodes) {
                        return;
                    }
                    potentialNodes.forEach(function(report) {
                        // only reports nodes that belong to the same expression
                        if (report.block === statement.parent) {
                            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);
            }
        }
    };
});
 
module.exports.schema = [{
    type: 'object',
    properties: {
        ignoreReplaceFalse: {
            type: 'boolean'
        }
    }
}];