All files / src/rules sorted-specifiers.ts

100% Statements 20/20
100% Branches 4/4
100% Functions 5/5
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78    1x 1x 1x         1x       1x                   4x   4x   4x         4x   9x 9x         9x 2x     2x         2x   3x     2x       5x     2x           2x                    
import { Rule } from "eslint";
import { ImportDeclaration } from "estree";
import { messages } from "../constants/messages";
import { nodesArrayToText, getNodeEndPosition } from "../services/eslint";
import {
  getFirstNotSorted,
  createCalculateSpecifierSortIndex,
} from "../services/imports";
 
const opts = {
  DISABLE_LINE_SORTS: "no-line-length-sort",
};
 
export default {
  meta: {
    fixable: "code",
  },
  schema: [
    {
      enum: [opts.DISABLE_LINE_SORTS],
    },
  ],
  create: (context: Rule.RuleContext) => {
    const sourceCode = context.getSourceCode();
 
    const disableLineSorts = context.options.includes(opts.DISABLE_LINE_SORTS);
 
    const calculateSpecifierSortIndex = createCalculateSpecifierSortIndex(
      sourceCode,
      { disableLineSorts }
    );
 
    return {
      ImportDeclaration: (node: ImportDeclaration) => {
        const specifiers = node.specifiers;
        const firstNotSorted = getFirstNotSorted(
          specifiers,
          calculateSpecifierSortIndex
        );
 
        if (firstNotSorted) {
          const autoFix = (fixer: Rule.RuleFixer) => {
            /* istanbul ignore next */
            const specifiersStart = specifiers[0].range?.[0] ?? 0;
            const specifiersEnd = getNodeEndPosition(
              sourceCode,
              specifiers[specifiers.length - 1]
            );
 
            const sortedSpecifiers = specifiers.sort(
              (a, b) =>
                calculateSpecifierSortIndex(a) - calculateSpecifierSortIndex(b)
            );
 
            const sortedSpecifiersText = nodesArrayToText(sourceCode)(
              sortedSpecifiers,
              // do not add additional \n to the end of imports
              (source, index) =>
                index < sortedSpecifiers.length - 1 ? source + ", " : source
            );
 
            return fixer.replaceTextRange(
              [specifiersStart, specifiersEnd],
              sortedSpecifiersText
            );
          };
 
          context.report({
            fix: autoFix,
            loc: firstNotSorted.loc!,
            message: messages.NOT_SORTED_SPECIFIERS,
          });
        }
      },
    } as Rule.RuleListener;
  },
} as Rule.RuleModule;