core/quality/eslint/no-deprecated-api.eslint.rule.ts

core/quality/eslint/no-deprecated-api.eslint.rule.ts is a file in GovLab Quality. 71 lines of code and 11 definitions.

import { DEPRECATED_CTORS, DEPRECATED_GLOBALS, DEPRECATED_MEMBERS } from "#configuration/constants/idiom.constants";
import { asNode, identName } from "#core/selectors/syntax.selector";
import type { DeprecatedApi } from "#types/idiom.types";
import type { Rule } from "eslint";
import { govlabMeta } from "#core/factories/eslint.factory";

const reportEntry = (
    context: Rule.RuleContext,
    node: Rule.Node,
    payload: { entry: DeprecatedApi; name: string },
): void => {
    context.report({
        data: { name: payload.name, reason: payload.entry.reason, replacement: payload.entry.replacement },
        messageId: "deprecated",
        node,
    });
};

const reportCall = function reportCall(context: Rule.RuleContext, node: Rule.Node): void {
    const callee = asNode(node)?.callee;
    const name = callee?.type === "Identifier" ? identName(callee) : null;
    const entry = DEPRECATED_GLOBALS.get(name ?? "");
    if (entry && name !== null) {
        reportEntry(context, node, { entry, name: `${name}()` });
    }
};

const reportMember = function reportMember(context: Rule.RuleContext, node: Rule.Node): void {
    const member = asNode(node);
    const prop = member === null ? null : identName(member.property);
    const entry = DEPRECATED_MEMBERS.get(prop ?? "");
    if (entry && prop !== null) {
        reportEntry(context, node, { entry, name: `.${prop}` });
    }
};

const reportNew = function reportNew(context: Rule.RuleContext, node: Rule.Node): void {
    const callee = asNode(node)?.callee;
    const name = callee?.type === "Identifier" ? identName(callee) : null;
    const entry = DEPRECATED_CTORS.get(name ?? "");
    if (entry && name !== null) {
        reportEntry(context, node, { entry, name: `new ${name}()` });
    }
};

export default {
    create(context: Rule.RuleContext): Rule.RuleListener {
        const handlers: [string, (node: Rule.Node) => void][] = [
            [
                "CallExpression",
                (node): void => {
                    reportCall(context, node);
                },
            ],
            [
                "MemberExpression",
                (node): void => {
                    reportMember(context, node);
                },
            ],
            [
                "NewExpression",
                (node): void => {
                    reportNew(context, node);
                },
            ],
        ];
        return Object.fromEntries(handlers);
    },
    meta: govlabMeta({
        canonical: ["deprecated-api", "idiomatic-preference"],
        description: "Ban deprecated / legacy JavaScript APIs in favor of their modern, supported replacements",
        messages: { deprecated: "'{{name}}' is deprecated — {{reason}}. Use {{replacement}} instead." },
        ruleId: "no_deprecated_api",
    }),
} satisfies Rule.RuleModule;