source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/jsx-max-depth.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/**
2 * @fileoverview Validate JSX maximum depth
3 * @author Chris<wfsr@foxmail.com>
4 */
5
6'use strict';
7
8const has = require('hasown');
9const includes = require('array-includes');
10const variableUtil = require('../util/variable');
11const jsxUtil = require('../util/jsx');
12const docsUrl = require('../util/docsUrl');
13const reportC = require('../util/report');
14
15// ------------------------------------------------------------------------------
16// Rule Definition
17// ------------------------------------------------------------------------------
18
19const messages = {
20 wrongDepth: 'Expected the depth of nested jsx elements to be <= {{needed}}, but found {{found}}.',
21};
22
23/** @type {import('eslint').Rule.RuleModule} */
24module.exports = {
25 meta: {
26 docs: {
27 description: 'Enforce JSX maximum depth',
28 category: 'Stylistic Issues',
29 recommended: false,
30 url: docsUrl('jsx-max-depth'),
31 },
32
33 messages,
34
35 schema: [
36 {
37 type: 'object',
38 properties: {
39 max: {
40 type: 'integer',
41 minimum: 0,
42 },
43 },
44 additionalProperties: false,
45 },
46 ],
47 },
48 create(context) {
49 const DEFAULT_DEPTH = 2;
50
51 const option = context.options[0] || {};
52 const maxDepth = has(option, 'max') ? option.max : DEFAULT_DEPTH;
53
54 function isExpression(node) {
55 return node.type === 'JSXExpressionContainer';
56 }
57
58 function hasJSX(node) {
59 return jsxUtil.isJSX(node) || (isExpression(node) && jsxUtil.isJSX(node.expression));
60 }
61
62 function isLeaf(node) {
63 const children = node.children;
64
65 return !children || children.length === 0 || !children.some(hasJSX);
66 }
67
68 function getDepth(node) {
69 let count = 0;
70
71 while (jsxUtil.isJSX(node.parent) || isExpression(node.parent)) {
72 node = node.parent;
73 if (jsxUtil.isJSX(node)) {
74 count += 1;
75 }
76 }
77
78 return count;
79 }
80
81 function report(node, depth) {
82 reportC(context, messages.wrongDepth, 'wrongDepth', {
83 node,
84 data: {
85 found: depth,
86 needed: maxDepth,
87 },
88 });
89 }
90
91 function findJSXElementOrFragment(startNode, name, previousReferences) {
92 function find(refs, prevRefs) {
93 for (let i = refs.length - 1; i >= 0; i--) {
94 if (has(refs[i], 'writeExpr')) {
95 const writeExpr = refs[i].writeExpr;
96
97 return (jsxUtil.isJSX(writeExpr)
98 && writeExpr)
99 || ((writeExpr && writeExpr.type === 'Identifier')
100 && findJSXElementOrFragment(startNode, writeExpr.name, prevRefs));
101 }
102 }
103
104 return null;
105 }
106
107 const variable = variableUtil.getVariableFromContext(context, startNode, name);
108 if (variable && variable.references) {
109 const containDuplicates = previousReferences.some((ref) => includes(variable.references, ref));
110
111 // Prevent getting stuck in circular references
112 if (containDuplicates) {
113 return false;
114 }
115
116 return find(variable.references, previousReferences.concat(variable.references));
117 }
118
119 return false;
120 }
121
122 function checkDescendant(baseDepth, children) {
123 baseDepth += 1;
124 (children || []).filter((node) => hasJSX(node)).forEach((node) => {
125 if (baseDepth > maxDepth) {
126 report(node, baseDepth);
127 } else if (!isLeaf(node)) {
128 checkDescendant(baseDepth, node.children);
129 }
130 });
131 }
132
133 function handleJSX(node) {
134 if (!isLeaf(node)) {
135 return;
136 }
137
138 const depth = getDepth(node);
139 if (depth > maxDepth) {
140 report(node, depth);
141 }
142 }
143
144 return {
145 JSXElement: handleJSX,
146 JSXFragment: handleJSX,
147
148 JSXExpressionContainer(node) {
149 if (node.expression.type !== 'Identifier') {
150 return;
151 }
152
153 const element = findJSXElementOrFragment(node, node.expression.name, []);
154
155 if (element) {
156 const baseDepth = getDepth(node);
157 checkDescendant(baseDepth, element.children);
158 }
159 },
160 };
161 },
162};
Note: See TracBrowser for help on using the repository browser.