UNPKG

3.99 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to require sorting of variables within a single Variable Declaration block
3 * @author Ilya Volodin
4 */
5
6"use strict";
7
8//------------------------------------------------------------------------------
9// Rule Definition
10//------------------------------------------------------------------------------
11
12module.exports = {
13 meta: {
14 docs: {
15 description: "require variables within the same declaration block to be sorted",
16 category: "Stylistic Issues",
17 recommended: false,
18 url: "https://eslint.org/docs/rules/sort-vars"
19 },
20
21 schema: [
22 {
23 type: "object",
24 properties: {
25 ignoreCase: {
26 type: "boolean"
27 }
28 },
29 additionalProperties: false
30 }
31 ],
32
33 fixable: "code"
34 },
35
36 create(context) {
37
38 const configuration = context.options[0] || {},
39 ignoreCase = configuration.ignoreCase || false,
40 sourceCode = context.getSourceCode();
41
42 return {
43 VariableDeclaration(node) {
44 const idDeclarations = node.declarations.filter(decl => decl.id.type === "Identifier");
45 const getSortableName = ignoreCase ? decl => decl.id.name.toLowerCase() : decl => decl.id.name;
46 const unfixable = idDeclarations.some(decl => decl.init !== null && decl.init.type !== "Literal");
47 let fixed = false;
48
49 idDeclarations.slice(1).reduce((memo, decl) => {
50 const lastVariableName = getSortableName(memo),
51 currentVariableName = getSortableName(decl);
52
53 if (currentVariableName < lastVariableName) {
54 context.report({
55 node: decl,
56 message: "Variables within the same declaration block should be sorted alphabetically.",
57 fix(fixer) {
58 if (unfixable || fixed) {
59 return null;
60 }
61 return fixer.replaceTextRange(
62 [idDeclarations[0].range[0], idDeclarations[idDeclarations.length - 1].range[1]],
63 idDeclarations
64
65 // Clone the idDeclarations array to avoid mutating it
66 .slice()
67
68 // Sort the array into the desired order
69 .sort((declA, declB) => {
70 const aName = getSortableName(declA);
71 const bName = getSortableName(declB);
72
73 return aName > bName ? 1 : -1;
74 })
75
76 // Build a string out of the sorted list of identifier declarations and the text between the originals
77 .reduce((sourceText, identifier, index) => {
78 const textAfterIdentifier = index === idDeclarations.length - 1
79 ? ""
80 : sourceCode.getText().slice(idDeclarations[index].range[1], idDeclarations[index + 1].range[0]);
81
82 return sourceText + sourceCode.getText(identifier) + textAfterIdentifier;
83 }, "")
84
85 );
86 }
87 });
88 fixed = true;
89 return memo;
90 }
91 return decl;
92
93 }, idDeclarations[0]);
94 }
95 };
96 }
97};