minor adjustment to readme
[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 natual.
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
115     create(context) {
116
117         // Parse options.
118         const order = context.options[0] || "asc";
119         const options = context.options[1];
120         const insensitive = options && options.caseSensitive === false;
121         const natual = options && options.natural;
122         const minKeys = options && options.minKeys;
123         const isValidOrder = isValidOrders[
124             order + (insensitive ? "I" : "") + (natual ? "N" : "")
125         ];
126
127         // The stack to save the previous property's name for each object literals.
128         let stack = null;
129
130         return {
131             ObjectExpression(node) {
132                 stack = {
133                     upper: stack,
134                     prevName: null,
135                     numKeys: node.properties.length
136                 };
137             },
138
139             "ObjectExpression:exit"() {
140                 stack = stack.upper;
141             },
142
143             SpreadElement(node) {
144                 if (node.parent.type === "ObjectExpression") {
145                     stack.prevName = null;
146                 }
147             },
148
149             Property(node) {
150                 if (node.parent.type === "ObjectPattern") {
151                     return;
152                 }
153
154                 const prevName = stack.prevName;
155                 const numKeys = stack.numKeys;
156                 const thisName = getPropertyName(node);
157
158                 if (thisName !== null) {
159                     stack.prevName = thisName;
160                 }
161
162                 if (prevName === null || thisName === null || numKeys < minKeys) {
163                     return;
164                 }
165
166                 if (!isValidOrder(prevName, thisName)) {
167                     context.report({
168                         node,
169                         loc: node.key.loc,
170                         message: "Expected object keys to be in {{natual}}{{insensitive}}{{order}}ending order. '{{thisName}}' should be before '{{prevName}}'.",
171                         data: {
172                             thisName,
173                             prevName,
174                             order,
175                             insensitive: insensitive ? "insensitive " : "",
176                             natual: natual ? "natural " : ""
177                         }
178                     });
179                 }
180             }
181         };
182     }
183 };