source: imaps-frontend/node_modules/eslint/lib/rules/sort-keys.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 7.2 KB
Line 
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
12const 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 */
30function 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 */
47const 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/** @type {import('../shared/types').Rule} */
79module.exports = {
80 meta: {
81 type: "suggestion",
82
83 docs: {
84 description: "Require object keys to be sorted",
85 recommended: false,
86 url: "https://eslint.org/docs/latest/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 allowLineSeparatedGroups: {
110 type: "boolean",
111 default: false
112 }
113 },
114 additionalProperties: false
115 }
116 ],
117
118 messages: {
119 sortKeys: "Expected object keys to be in {{natural}}{{insensitive}}{{order}}ending order. '{{thisName}}' should be before '{{prevName}}'."
120 }
121 },
122
123 create(context) {
124
125 // Parse options.
126 const order = context.options[0] || "asc";
127 const options = context.options[1];
128 const insensitive = options && options.caseSensitive === false;
129 const natural = options && options.natural;
130 const minKeys = options && options.minKeys;
131 const allowLineSeparatedGroups = options && options.allowLineSeparatedGroups || false;
132 const isValidOrder = isValidOrders[
133 order + (insensitive ? "I" : "") + (natural ? "N" : "")
134 ];
135
136 // The stack to save the previous property's name for each object literals.
137 let stack = null;
138 const sourceCode = context.sourceCode;
139
140 return {
141 ObjectExpression(node) {
142 stack = {
143 upper: stack,
144 prevNode: null,
145 prevBlankLine: false,
146 prevName: null,
147 numKeys: node.properties.length
148 };
149 },
150
151 "ObjectExpression:exit"() {
152 stack = stack.upper;
153 },
154
155 SpreadElement(node) {
156 if (node.parent.type === "ObjectExpression") {
157 stack.prevName = null;
158 }
159 },
160
161 Property(node) {
162 if (node.parent.type === "ObjectPattern") {
163 return;
164 }
165
166 const prevName = stack.prevName;
167 const numKeys = stack.numKeys;
168 const thisName = getPropertyName(node);
169
170 // Get tokens between current node and previous node
171 const tokens = stack.prevNode && sourceCode
172 .getTokensBetween(stack.prevNode, node, { includeComments: true });
173
174 let isBlankLineBetweenNodes = stack.prevBlankLine;
175
176 if (tokens) {
177
178 // check blank line between tokens
179 tokens.forEach((token, index) => {
180 const previousToken = tokens[index - 1];
181
182 if (previousToken && (token.loc.start.line - previousToken.loc.end.line > 1)) {
183 isBlankLineBetweenNodes = true;
184 }
185 });
186
187 // check blank line between the current node and the last token
188 if (!isBlankLineBetweenNodes && (node.loc.start.line - tokens[tokens.length - 1].loc.end.line > 1)) {
189 isBlankLineBetweenNodes = true;
190 }
191
192 // check blank line between the first token and the previous node
193 if (!isBlankLineBetweenNodes && (tokens[0].loc.start.line - stack.prevNode.loc.end.line > 1)) {
194 isBlankLineBetweenNodes = true;
195 }
196 }
197
198 stack.prevNode = node;
199
200 if (thisName !== null) {
201 stack.prevName = thisName;
202 }
203
204 if (allowLineSeparatedGroups && isBlankLineBetweenNodes) {
205 stack.prevBlankLine = thisName === null;
206 return;
207 }
208
209 if (prevName === null || thisName === null || numKeys < minKeys) {
210 return;
211 }
212
213 if (!isValidOrder(prevName, thisName)) {
214 context.report({
215 node,
216 loc: node.key.loc,
217 messageId: "sortKeys",
218 data: {
219 thisName,
220 prevName,
221 order,
222 insensitive: insensitive ? "insensitive " : "",
223 natural: natural ? "natural " : ""
224 }
225 });
226 }
227 }
228 };
229 }
230};
Note: See TracBrowser for help on using the repository browser.