105 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * @fileoverview Rule to require sorting of variables within a single Variable Declaration block
 | 
						|
 * @author Ilya Volodin
 | 
						|
 */
 | 
						|
 | 
						|
"use strict";
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// Rule Definition
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
 | 
						|
/** @type {import('../shared/types').Rule} */
 | 
						|
module.exports = {
 | 
						|
    meta: {
 | 
						|
        type: "suggestion",
 | 
						|
 | 
						|
        docs: {
 | 
						|
            description: "Require variables within the same declaration block to be sorted",
 | 
						|
            recommended: false,
 | 
						|
            url: "https://eslint.org/docs/latest/rules/sort-vars"
 | 
						|
        },
 | 
						|
 | 
						|
        schema: [
 | 
						|
            {
 | 
						|
                type: "object",
 | 
						|
                properties: {
 | 
						|
                    ignoreCase: {
 | 
						|
                        type: "boolean",
 | 
						|
                        default: false
 | 
						|
                    }
 | 
						|
                },
 | 
						|
                additionalProperties: false
 | 
						|
            }
 | 
						|
        ],
 | 
						|
 | 
						|
        fixable: "code",
 | 
						|
 | 
						|
        messages: {
 | 
						|
            sortVars: "Variables within the same declaration block should be sorted alphabetically."
 | 
						|
        }
 | 
						|
    },
 | 
						|
 | 
						|
    create(context) {
 | 
						|
 | 
						|
        const configuration = context.options[0] || {},
 | 
						|
            ignoreCase = configuration.ignoreCase || false,
 | 
						|
            sourceCode = context.sourceCode;
 | 
						|
 | 
						|
        return {
 | 
						|
            VariableDeclaration(node) {
 | 
						|
                const idDeclarations = node.declarations.filter(decl => decl.id.type === "Identifier");
 | 
						|
                const getSortableName = ignoreCase ? decl => decl.id.name.toLowerCase() : decl => decl.id.name;
 | 
						|
                const unfixable = idDeclarations.some(decl => decl.init !== null && decl.init.type !== "Literal");
 | 
						|
                let fixed = false;
 | 
						|
 | 
						|
                idDeclarations.slice(1).reduce((memo, decl) => {
 | 
						|
                    const lastVariableName = getSortableName(memo),
 | 
						|
                        currentVariableName = getSortableName(decl);
 | 
						|
 | 
						|
                    if (currentVariableName < lastVariableName) {
 | 
						|
                        context.report({
 | 
						|
                            node: decl,
 | 
						|
                            messageId: "sortVars",
 | 
						|
                            fix(fixer) {
 | 
						|
                                if (unfixable || fixed) {
 | 
						|
                                    return null;
 | 
						|
                                }
 | 
						|
                                return fixer.replaceTextRange(
 | 
						|
                                    [idDeclarations[0].range[0], idDeclarations[idDeclarations.length - 1].range[1]],
 | 
						|
                                    idDeclarations
 | 
						|
 | 
						|
                                        // Clone the idDeclarations array to avoid mutating it
 | 
						|
                                        .slice()
 | 
						|
 | 
						|
                                        // Sort the array into the desired order
 | 
						|
                                        .sort((declA, declB) => {
 | 
						|
                                            const aName = getSortableName(declA);
 | 
						|
                                            const bName = getSortableName(declB);
 | 
						|
 | 
						|
                                            return aName > bName ? 1 : -1;
 | 
						|
                                        })
 | 
						|
 | 
						|
                                        // Build a string out of the sorted list of identifier declarations and the text between the originals
 | 
						|
                                        .reduce((sourceText, identifier, index) => {
 | 
						|
                                            const textAfterIdentifier = index === idDeclarations.length - 1
 | 
						|
                                                ? ""
 | 
						|
                                                : sourceCode.getText().slice(idDeclarations[index].range[1], idDeclarations[index + 1].range[0]);
 | 
						|
 | 
						|
                                            return sourceText + sourceCode.getText(identifier) + textAfterIdentifier;
 | 
						|
                                        }, "")
 | 
						|
 | 
						|
                                );
 | 
						|
                            }
 | 
						|
                        });
 | 
						|
                        fixed = true;
 | 
						|
                        return memo;
 | 
						|
                    }
 | 
						|
                    return decl;
 | 
						|
 | 
						|
                }, idDeclarations[0]);
 | 
						|
            }
 | 
						|
        };
 | 
						|
    }
 | 
						|
};
 |