UNPKG

3.98 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule that warns when identifier names that are
3 * blacklisted in the configuration are used.
4 * @author Keith Cirkel (http://keithcirkel.co.uk)
5 */
6
7"use strict";
8
9//------------------------------------------------------------------------------
10// Rule Definition
11//------------------------------------------------------------------------------
12
13module.exports = {
14 meta: {
15 docs: {
16 description: "disallow specified identifiers",
17 category: "Stylistic Issues",
18 recommended: false
19 },
20
21 schema: {
22 type: "array",
23 items: {
24 type: "string"
25 },
26 uniqueItems: true
27 }
28 },
29
30 create(context) {
31
32
33 //--------------------------------------------------------------------------
34 // Helpers
35 //--------------------------------------------------------------------------
36
37 const blacklist = context.options;
38
39
40 /**
41 * Checks if a string matches the provided pattern
42 * @param {string} name The string to check.
43 * @returns {boolean} if the string is a match
44 * @private
45 */
46 function isInvalid(name) {
47 return blacklist.indexOf(name) !== -1;
48 }
49
50 /**
51 * Verifies if we should report an error or not based on the effective
52 * parent node and the identifier name.
53 * @param {ASTNode} effectiveParent The effective parent node of the node to be reported
54 * @param {string} name The identifier name of the identifier node
55 * @returns {boolean} whether an error should be reported or not
56 */
57 function shouldReport(effectiveParent, name) {
58 return effectiveParent.type !== "CallExpression" &&
59 effectiveParent.type !== "NewExpression" &&
60 isInvalid(name);
61 }
62
63 /**
64 * Reports an AST node as a rule violation.
65 * @param {ASTNode} node The node to report.
66 * @returns {void}
67 * @private
68 */
69 function report(node) {
70 context.report({
71 node,
72 message: "Identifier '{{name}}' is blacklisted.",
73 data: {
74 name: node.name
75 }
76 });
77 }
78
79 return {
80
81 Identifier(node) {
82 const name = node.name,
83 effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
84
85 // MemberExpressions get special rules
86 if (node.parent.type === "MemberExpression") {
87
88 // Always check object names
89 if (node.parent.object.type === "Identifier" &&
90 node.parent.object.name === node.name) {
91 if (isInvalid(name)) {
92 report(node);
93 }
94
95 // Report AssignmentExpressions only if they are the left side of the assignment
96 } else if (effectiveParent.type === "AssignmentExpression" &&
97 (effectiveParent.right.type !== "MemberExpression" ||
98 effectiveParent.left.type === "MemberExpression" &&
99 effectiveParent.left.property.name === node.name)) {
100 if (isInvalid(name)) {
101 report(node);
102 }
103 }
104
105 // Properties have their own rules
106 } else if (node.parent.type === "Property") {
107
108 if (shouldReport(effectiveParent, name)) {
109 report(node);
110 }
111
112 // Report anything that is a match and not a CallExpression
113 } else if (shouldReport(effectiveParent, name)) {
114 report(node);
115 }
116 }
117
118 };
119
120 }
121};