UNPKG

eslint-plugin-react-debug

Version:

ESLint React's ESLint plugin for debugging related rules.

345 lines (333 loc) • 9.88 kB
'use strict'; var shared = require('@eslint-react/shared'); var ER2 = require('@eslint-react/core'); var utils = require('@typescript-eslint/utils'); var eff = require('@eslint-react/eff'); var kit = require('@eslint-react/kit'); var types = require('@typescript-eslint/types'); var tsPattern = require('ts-pattern'); var typescript = require('typescript'); function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var ER2__namespace = /*#__PURE__*/_interopNamespace(ER2); var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name3 in all) __defProp(target, name3, { get: all[name3], enumerable: true }); }; // src/configs/all.ts var all_exports = {}; __export(all_exports, { name: () => name, rules: () => rules, settings: () => settings }); var name = "react-debug/all"; var rules = { "react-debug/class-component": "warn", "react-debug/function-component": "warn", "react-debug/hook": "warn", "react-debug/is-from-react": "warn", "react-debug/jsx": "warn" }; var settings = { "react-x": shared.DEFAULT_ESLINT_REACT_SETTINGS }; // package.json var name2 = "eslint-plugin-react-debug"; var version = "1.47.4"; var createRule = utils.ESLintUtils.RuleCreator(shared.getDocsUrl("debug")); // src/utils/stringify.ts function stringify(value) { return JSON.stringify(value, null, 2); } // src/rules/class-component.ts var RULE_NAME = "class-component"; var RULE_FEATURES = [ "DBG" ]; var class_component_default = createRule({ meta: { type: "problem", docs: { description: "Reports all class components.", [Symbol.for("rule_features")]: RULE_FEATURES }, messages: { classComponent: "{{json}}" }, schema: [] }, name: RULE_NAME, create, defaultOptions: [] }); function create(context) { const { ctx, listeners } = ER2__namespace.useComponentCollectorLegacy(); return { ...listeners, "Program:exit"(program) { const components = ctx.getAllComponents(program); for (const { name: name3 = "anonymous", node: component } of components.values()) { context.report({ messageId: "classComponent", node: component, data: { json: stringify({ name: name3 }) } }); } } }; } var RULE_NAME2 = "function-component"; var RULE_FEATURES2 = [ "DBG" ]; var function_component_default = createRule({ meta: { type: "problem", docs: { description: "Reports all function components.", [Symbol.for("rule_features")]: RULE_FEATURES2 }, messages: { functionComponent: "{{json}}" // "[function component] name: {{name}}, memo: {{memo}}, forwardRef: {{forwardRef}}, hookCalls: {{hookCalls}}, displayName: {{displayName}}.", }, schema: [] }, name: RULE_NAME2, create: create2, defaultOptions: [] }); function create2(context) { const { ctx, listeners } = ER2__namespace.useComponentCollector( context, { collectDisplayName: true, collectHookCalls: true, hint: ER2__namespace.DEFAULT_COMPONENT_DETECTION_HINT } ); return { ...listeners, "Program:exit"(program) { const components = ctx.getAllComponents(program); for (const { name: name3 = "anonymous", node, displayName, flag, hookCalls } of components.values()) { context.report({ messageId: "functionComponent", node, data: { json: stringify({ name: name3, displayName: displayName == null ? "none" : context.sourceCode.getText(displayName), forwardRef: (flag & ER2__namespace.ComponentFlag.ForwardRef) > 0n, hookCalls: hookCalls.length, memo: (flag & ER2__namespace.ComponentFlag.Memo) > 0n }) } }); } } }; } var RULE_NAME3 = "hook"; var RULE_FEATURES3 = [ "DBG" ]; var hook_default = createRule({ meta: { type: "problem", docs: { description: "Reports all React Hooks.", [Symbol.for("rule_features")]: RULE_FEATURES3 }, messages: { hook: "{{json}}" }, schema: [] }, name: RULE_NAME3, create: create3, defaultOptions: [] }); function create3(context) { const { ctx, listeners } = ER2__namespace.useHookCollector(); return { ...listeners, "Program:exit"(program) { const allHooks = ctx.getAllHooks(program); for (const { name: name3, node, hookCalls } of allHooks.values()) { context.report({ messageId: "hook", node, data: { json: stringify({ name: name3, hookCalls: hookCalls.length }) } }); } } }; } var RULE_NAME4 = "is-from-react"; var RULE_FEATURES4 = [ "DBG" ]; var is_from_react_default = createRule({ meta: { type: "problem", docs: { description: "Reports all identifiers that are initialized from React.", [Symbol.for("rule_features")]: RULE_FEATURES4 }, messages: { isFromReact: "{{json}}" }, schema: [] }, name: RULE_NAME4, create: create4, defaultOptions: [] }); function create4(context) { const { importSource = "react" } = shared.getSettingsFromContext(context); function isFromReact(node, initialScope) { const name3 = node.name; switch (true) { case (node.parent.type === utils.AST_NODE_TYPES.MemberExpression && node.parent.property === node && node.parent.object.type === utils.AST_NODE_TYPES.Identifier): return ER2__namespace.isInitializedFromReact(node.parent.object.name, importSource, initialScope); case (node.parent.type === utils.AST_NODE_TYPES.JSXMemberExpression && node.parent.property === node && node.parent.object.type === utils.AST_NODE_TYPES.JSXIdentifier): return ER2__namespace.isInitializedFromReact(node.parent.object.name, importSource, initialScope); default: return ER2__namespace.isInitializedFromReact(name3, importSource, initialScope); } } function visitorFunction(node) { const shouldSkipDuplicate = node.parent.type === utils.AST_NODE_TYPES.ImportSpecifier && node.parent.imported === node && node.parent.imported.name === node.parent.local.name; if (shouldSkipDuplicate) return; const name3 = node.name; const initialScope = context.sourceCode.getScope(node); if (!isFromReact(node, initialScope)) return; context.report({ messageId: "isFromReact", node, data: { json: stringify({ name: name3, importSource }) } }); } return { Identifier: visitorFunction, JSXIdentifier: visitorFunction }; } var RULE_NAME5 = "jsx"; var RULE_FEATURES5 = [ "DBG" ]; var jsx_default = createRule({ meta: { type: "problem", docs: { description: "Reports all JSX elements and fragments.", [Symbol.for("rule_features")]: RULE_FEATURES5 }, messages: { jsx: "{{json}}" }, schema: [] }, name: RULE_NAME5, create: create5, defaultOptions: [] }); function create5(context) { const jsxConfigFromContext = kit.JsxConfig.getFromContext(context); const jsxConfigFromAnnotation = kit.JsxConfig.getFromAnnotation(context); const jsxConfig = { ...jsxConfigFromContext, ...jsxConfigFromAnnotation }; function getReportDescriptor(context2) { return (node) => ({ messageId: "jsx", node, data: { json: stringify({ kind: tsPattern.match(node).with({ type: types.AST_NODE_TYPES.JSXElement }, (n) => ER2__namespace.isFragmentElement(context2, n) ? "fragment" : "element").with({ type: types.AST_NODE_TYPES.JSXFragment }, () => "fragment").exhaustive(), type: ER2__namespace.getElementType(context2, node), jsx: tsPattern.match(jsxConfig.jsx).with(typescript.JsxEmit.None, () => "none").with(typescript.JsxEmit.ReactJSX, () => "react-jsx").with(typescript.JsxEmit.ReactJSXDev, () => "react-jsx-dev").with(typescript.JsxEmit.React, () => "react").with(typescript.JsxEmit.ReactNative, () => "react-native").with(typescript.JsxEmit.Preserve, () => "preserve").otherwise(() => "unknown"), jsxFactory: jsxConfig.jsxFactory, jsxFragmentFactory: jsxConfig.jsxFragmentFactory, jsxImportSource: jsxConfig.jsxImportSource, jsxRuntime: tsPattern.match(jsxConfig.jsx).with(tsPattern.P.union(typescript.JsxEmit.None, typescript.JsxEmit.ReactJSX, typescript.JsxEmit.ReactJSXDev), () => "automatic").otherwise(() => "classic") }) } }); } return { "JSXElement, JSXFragment": eff.flow(getReportDescriptor(context), kit.Reporter.make(context).send) }; } // src/plugin.ts var plugin = { meta: { name: name2, version }, rules: { ["class-component"]: class_component_default, ["function-component"]: function_component_default, ["hook"]: hook_default, ["is-from-react"]: is_from_react_default, ["jsx"]: jsx_default, // Part: deprecated rules /** @deprecated Use `hook` instead */ "react-hooks": hook_default } }; // src/index.ts function makeConfig(config) { return { ...config, plugins: { "react-debug": plugin } }; } function makeLegacyConfig({ rules: rules2 }) { return { plugins: ["react-debug"], rules: rules2 }; } var index_default = { ...plugin, configs: { ["all"]: makeConfig(all_exports), ["all-legacy"]: makeLegacyConfig(all_exports) } }; module.exports = index_default;