.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / sort-keys.js
1 /**
2  * @fileoverview Rule to require object keys to be sorted
3  * @author Toru Nagashima
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils"),
13     naturalCompare = require("natural-compare");
14
15 //------------------------------------------------------------------------------
16 // Helpers
17 //------------------------------------------------------------------------------
18
19 /**
20  * Gets the property name of the given `Property` node.
21  *
22  * - If the property's key is an `Identifier` node, this returns the key's name
23  *   whether it's a computed property or not.
24  * - If the property has a static name, this returns the static name.
25  * - Otherwise, this returns null.
26  * @param {ASTNode} node The `Property` node to get.
27  * @returns {string|null} The property name or null.
28  * @private
29  */
30 function getPropertyName(node) {
31     const staticName = astUtils.getStaticPropertyName(node);
32
33     if (staticName !== null) {
34         return staticName;
35     }
36
37     return node.key.name || null;
38 }
39
40 /**
41  * Functions which check that the given 2 names are in specific order.
42  *
43  * Postfix `I` is meant insensitive.
44  * Postfix `N` is meant natural.
45  * @private
46  */
47 const isValidOrders = {
48     asc(a, b) {
49         return a <= b;
50     },
51     ascI(a, b) {
52         return a.toLowerCase() <= b.toLowerCase();
53     },
54     ascN(a, b) {
55         return naturalCompare(a, b) <= 0;
56     },
57     ascIN(a, b) {
58         return naturalCompare(a.toLowerCase(), b.toLowerCase()) <= 0;
59     },
60     desc(a, b) {
61         return isValidOrders.asc(b, a);
62     },
63     descI(a, b) {
64         return isValidOrders.ascI(b, a);
65     },
66     descN(a, b) {
67         return isValidOrders.ascN(b, a);
68     },
69     descIN(a, b) {
70         return isValidOrders.ascIN(b, a);
71     }
72 };
73
74 //------------------------------------------------------------------------------
75 // Rule Definition
76 //------------------------------------------------------------------------------
77
78 module.exports = {
79     meta: {
80         type: "suggestion",
81
82         docs: {
83             description: "require object keys to be sorted",
84             category: "Stylistic Issues",
85             recommended: false,
86             url: "https://eslint.org/docs/rules/sort-keys"
87         },
88
89         schema: [
90             {
91                 enum: ["asc", "desc"]
92             },
93             {
94                 type: "object",
95                 properties: {
96                     caseSensitive: {
97                         type: "boolean",
98                         default: true
99                     },
100                     natural: {
101                         type: "boolean",
102                         default: false
103                     },
104                     minKeys: {
105                         type: "integer",
106                         minimum: 2,
107                         default: 2
108                     }
109                 },
110                 additionalProperties: false
111             }
112         ],
113
114         messages: {
115             sortKeys: "Expected object keys to be in {{natural}}{{insensitive}}{{order}}ending order. '{{thisName}}' should be before '{{prevName}}'."
116         }
117     },
118
119     create(context) {
120
121         // Parse options.
122         const order = context.options[0] || "asc";
123         const options = context.options[1];
124         const insensitive = options && options.caseSensitive === false;
125         const natural = options && options.natural;
126         const minKeys = options && options.minKeys;
127         const isValidOrder = isValidOrders[
128             order + (insensitive ? "I" : "") + (natural ? "N" : "")
129         ];
130
131         // The stack to save the previous property's name for each object literals.
132         let stack = null;
133
134         return {
135             ObjectExpression(node) {
136                 stack = {
137                     upper: stack,
138                     prevName: null,
139                     numKeys: node.properties.length
140                 };
141             },
142
143             "ObjectExpression:exit"() {
144                 stack = stack.upper;
145             },
146
147             SpreadElement(node) {
148                 if (node.parent.type === "ObjectExpression") {
149                     stack.prevName = null;
150                 }
151             },
152
153             Property(node) {
154                 if (node.parent.type === "ObjectPattern") {
155                     return;
156                 }
157
158                 const prevName = stack.prevName;
159                 const numKeys = stack.numKeys;
160                 const thisName = getPropertyName(node);
161
162                 if (thisName !== null) {
163                     stack.prevName = thisName;
164                 }
165
166                 if (prevName === null || thisName === null || numKeys < minKeys) {
167                     return;
168                 }
169
170                 if (!isValidOrder(prevName, thisName)) {
171                     context.report({
172                         node,
173                         loc: node.key.loc,
174                         messageId: "sortKeys",
175                         data: {
176                             thisName,
177                             prevName,
178                             order,
179                             insensitive: insensitive ? "insensitive " : "",
180                             natural: natural ? "natural " : ""
181                         }
182                     });
183                 }
184             }
185         };
186     }
187 };