UNPKG

eslint-plugin-etc

Version:
143 lines (142 loc) 5.2 kB
"use strict"; const utils_1 = require("../utils"); const rule = (0, utils_1.ruleCreator)({ defaultOptions: [], meta: { docs: { description: "Forbids commented-out code.", recommended: false, }, fixable: undefined, hasSuggestions: false, messages: { forbidden: "Commented-out code is forbidden.", }, schema: [], type: "problem", }, name: "no-commented-out-code", create: (context) => { const { parse } = require(context.parserPath); const { project, ...parserOptions } = context.parserOptions; const sourceCode = context.getSourceCode(); return { Program: () => { const comments = context.getSourceCode().getAllComments(); const blocks = toBlocks(comments); for (const block of blocks) { const { content, loc } = block; if (isRegionComment(content)) { continue; } try { const program = parse(content, parserOptions); if (!hasEmptyBody(program) && !hasExpressionBody(program) && !hasLabeledStatementBody(program)) { context.report({ loc, messageId: "forbidden", }); } continue; } catch (error) { } const index = sourceCode.getIndexFromLoc(loc.start); const node = sourceCode.getNodeByRangeIndex(index); const wrappedContent = wrapContent(content, node); if (wrappedContent) { try { parse(wrappedContent, parserOptions); context.report({ loc, messageId: "forbidden", }); } catch (error) { } } } }, }; }, }); function hasEmptyBody(program) { return program.type === "Program" && program.body.length === 0; } function hasExpressionBody(program) { return (program.type === "Program" && program.body.every((statement) => statement.type === "ExpressionStatement" && isExpressionOrIdentifierOrLiteral(statement.expression))); } function hasLabeledStatementBody(program) { return (program.type === "Program" && program.body.length === 1 && program.body[0].type === "LabeledStatement"); } function isExpressionOrIdentifierOrLiteral(node) { if (node.type === "Identifier") { return true; } if (node.type === "Literal") { return true; } if (node.type === "BinaryExpression") { return (isExpressionOrIdentifierOrLiteral(node.left) && isExpressionOrIdentifierOrLiteral(node.right)); } return false; } function isRegionComment(content) { return /\s*#(end)?region/.test(content); } function toBlocks(comments) { const blocks = []; let prevLine; for (const comment of comments) { if (comment.type === "Block") { blocks.push({ content: comment.value.replace(/^\s*\*/, "").replace(/\n\s*\*/g, "\n"), loc: { ...comment.loc }, }); prevLine = undefined; } else if (comment.type === "Line") { if (prevLine && prevLine.loc.start.line === comment.loc.start.line - 1) { const prevBlock = blocks[blocks.length - 1]; prevBlock.content += `\n${comment.value}`; prevBlock.loc.end = comment.loc.end; } else { blocks.push({ content: comment.value, loc: { ...comment.loc }, }); } prevLine = comment; } } return blocks; } function wrapContent(content, node) { switch (node === null || node === void 0 ? void 0 : node.type) { case "ArrayExpression": return `let wrapper = [${content}]`; case "ClassBody": return `class Wrapper { ${content} }`; case "ImportDeclaration": return `import { ${content} } from "wrapper"`; case "ObjectExpression": return `let wrapper = { ${content} }`; case "FunctionDeclaration": return `function wrapper(${content}) {}`; case "SwitchStatement": return `switch (wrapper) { ${content} }`; case "TSInterfaceBody": return `interface Wrapper { ${content} }`; case "TSTypeLiteral": return `type Wrapper = { ${content} }`; default: return undefined; } } module.exports = rule;