d523aee5454efa11070a49bcc271a518ca6b76a7
[platform/framework/web/crosswalk-tizen.git] /
1 /**
2  * @fileoverview Rule to flag non-camelcased identifiers
3  * @author Nicholas C. Zakas
4  * @copyright 2015 Dieter Oberkofler. All rights reserved.
5  */
6
7 "use strict";
8
9 //------------------------------------------------------------------------------
10 // Rule Definition
11 //------------------------------------------------------------------------------
12
13 module.exports = function(context) {
14
15     //--------------------------------------------------------------------------
16     // Helpers
17     //--------------------------------------------------------------------------
18
19     /**
20      * Checks if a string contains an underscore and isn't all upper-case
21      * @param {String} name The string to check.
22      * @returns {boolean} if the string is underscored
23      * @private
24      */
25     function isUnderscored(name) {
26
27         // if there's an underscore, it might be A_CONSTANT, which is okay
28         return name.indexOf("_") > -1 && name !== name.toUpperCase();
29     }
30
31     /**
32      * Reports an AST node as a rule violation.
33      * @param {ASTNode} node The node to report.
34      * @returns {void}
35      * @private
36      */
37     function report(node) {
38         context.report(node, "Identifier '{{name}}' is not in camel case.", { name: node.name });
39     }
40
41     var options = context.options[0] || {},
42         properties = options.properties || "";
43
44     if (properties !== "always" && properties !== "never") {
45         properties = "always";
46     }
47
48     return {
49
50         "Identifier": function(node) {
51
52             // Leading and trailing underscores are commonly used to flag private/protected identifiers, strip them
53             var name = node.name.replace(/^_+|_+$/g, ""),
54                 effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent;
55
56             // MemberExpressions get special rules
57             if (node.parent.type === "MemberExpression") {
58
59                 // Always report underscored object names
60                 if (node.parent.object.type === "Identifier" &&
61                         node.parent.object.name === node.name &&
62                         isUnderscored(name)) {
63                     report(node);
64
65                 // Report AssignmentExpressions only if they are the left side of the assignment
66                 } else if (effectiveParent.type === "AssignmentExpression" &&
67                         isUnderscored(name) &&
68                         (effectiveParent.right.type !== "MemberExpression" ||
69                         effectiveParent.left.type === "MemberExpression" &&
70                         effectiveParent.left.property.name === node.name)) {
71                     report(node);
72                 }
73
74             // Properties have their own rules
75             } else if (node.parent.type === "Property") {
76
77                 // "never" check properties
78                 if (properties === "never") {
79                     return;
80                 }
81
82                 if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {
83                     report(node);
84                 }
85
86             // Report anything that is underscored that isn't a CallExpression
87             } else if (isUnderscored(name) && effectiveParent.type !== "CallExpression") {
88                 report(node);
89             }
90         }
91
92     };
93
94 };