UNPKG

eslint-plugin-ts-ban-snippets

Version:

Ban snippets of TypeScript from your project, using a custom eslint rule 'ts-ban-snippets'.

159 lines (158 loc) 6.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const experimental_utils_1 = require("@typescript-eslint/experimental-utils"); // ref = https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin-tslint/src/rules/config.ts const createRule = experimental_utils_1.ESLintUtils.RuleCreator((name) => { return `https://github.com/mrseanryan/eslint-plugin-ts-ban-snippets/blob/main/docs/${name}.md`; }); const BannedSnippetMessage = "'{{name}}' is a banned code snippet - {{message}} [{{ruleName}}]"; function isFileInPaths(filePath, paths) { return paths.some((path) => filePath.indexOf(path) >= 0); } const isRegexMatch = (regexRaw, text) => { const regex = new RegExp(regexRaw); return regex.test(text); }; const filterSnippets = (bannedSnippetsRaw, isRegex, text) => { const filterFun = (s) => { if (isRegex) return isRegexMatch(s, text); return text.startsWith(s); }; return bannedSnippetsRaw.filter(filterFun); }; const analyzeNodeFor = (node, banned, context, alreadyReported) => { const fileName = node.getSourceFile().fileName; if (!!banned.includePaths && !isFileInPaths(fileName, banned.includePaths)) return; if (!!banned.excludePaths && isFileInPaths(fileName, banned.excludePaths)) return; const text = node.getText(); node.getStart(); node.getEnd(); node.getSourceFile().getLineAndCharacterOfPosition(node.pos); if (!!banned.snippets && !!banned.regexSnippets) { throw new Error("Invalid config: 'snippets' and 'regexSnippets' are mutually exclusive."); } const bannedSnippetsRaw = banned.snippets || banned.regexSnippets || []; const isRegex = !!banned.regexSnippets; const bannedSnippets = filterSnippets(bannedSnippetsRaw, isRegex, text); if (bannedSnippets.length > 0) { const pos = node.getSourceFile().getLineAndCharacterOfPosition(node.pos); reportOnlyOnce(context, pos, bannedSnippets[0], banned, alreadyReported); } node.forEachChild((c) => analyzeNodeFor(c, banned, context, alreadyReported)); }; exports.default = createRule({ name: "ts-ban-snippets", meta: { type: "problem", docs: { description: "This TypeScript snippet is banned and should not be used.", category: "Possible Errors", recommended: "error", }, fixable: "code", messages: { BannedSnippetMessage, }, schema: [ { type: "object", properties: { banned: { type: "array", items: { type: "object", properties: { snippets: { type: "array", items: { type: "string", }, }, // regexSnippets and snippets are mutually exclusive regexSnippets: { type: "array", items: { type: "string", }, }, message: { type: "string", }, includePaths: { type: "array", items: { type: "string", }, }, excludePaths: { type: "array", items: { type: "string", }, }, }, additionalProperties: false, }, }, }, additionalProperties: false, }, ], }, defaultOptions: [{ banned: [] }], create: (context) => { if (!context.options[0]) { return { Program: () => { // do nothing }, }; } const parserServices = experimental_utils_1.ESLintUtils.getParserServices(context); /** * The TSLint rules configuration passed in by the user */ const banned = context.options[0].banned; return { Program: (node) => { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); // prevent duplicate errors: const alreadyReported = []; tsNode.forEachChild((child) => { banned.forEach((b) => analyzeNodeFor(child, b, context, alreadyReported)); }); }, }; }, }); function clone(obj) { return JSON.parse(JSON.stringify(obj, null, 0)); } function isAlreadyReported(id, alreadyReported) { const problemClone = clone(id); const json = JSON.stringify(problemClone, null, 0); if (alreadyReported.includes(json)) return true; alreadyReported.push(json); return false; } function reportOnlyOnce(context, pos, bannedSnippet, banned, alreadyReported) { const loc = { line: pos.line, column: pos.character, }; const problem = { loc: loc, messageId: "BannedSnippetMessage", data: { name: bannedSnippet, message: banned.message, ruleName: "ts-ban-snippets", }, }; if (!isAlreadyReported(loc, alreadyReported)) context.report(problem); }