@eslint-react/core 3.0.0-next.12 → 3.0.0-next.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -108,6 +108,68 @@ declare const ComponentDetectionHint: {
108
108
  * Default component detection hint
109
109
  */
110
110
  declare const DEFAULT_COMPONENT_DETECTION_HINT: bigint;
111
+ /**
112
+ * Check whether given node is a render method of a class component
113
+ * @example
114
+ * ```tsx
115
+ * class Component extends React.Component {
116
+ * renderHeader = () => <div />;
117
+ * renderFooter = () => <div />;
118
+ * }
119
+ * ```
120
+ * @param node The AST node to check
121
+ * @returns `true` if node is a render function, `false` if not
122
+ */
123
+ declare function isRenderMethodLike(node: TSESTree.Node): node is ast.TSESTreeMethodOrProperty;
124
+ /**
125
+ * Unsafe check whether given node is a render function
126
+ * ```tsx
127
+ * const renderRow = () => <div />
128
+ * ` ^^^^^^^^^^^^`
129
+ * _ = <Component renderRow={() => <div />} />
130
+ * ` ^^^^^^^^^^^^^ `
131
+ * ```
132
+ * @param context The rule context
133
+ * @param node The AST node to check
134
+ * @returns `true` if node is a render function, `false` if not
135
+ */
136
+ declare function isRenderFunctionLoose(context: RuleContext, node: TSESTree.Node): node is ast.TSESTreeFunction;
137
+ /**
138
+ * Unsafe check whether given JSXAttribute is a render prop
139
+ * ```tsx
140
+ * _ = <Component renderRow={() => <div />} />
141
+ * ` ^^^^^^^^^^^^^^^^^^^^^^^^^ `
142
+ * ```
143
+ * @param context The rule context
144
+ * @param node The AST node to check
145
+ * @returns `true` if node is a render prop, `false` if not
146
+ */
147
+ declare function isRenderPropLoose(context: RuleContext, node: TSESTree.JSXAttribute): boolean;
148
+ /**
149
+ * Unsafe check whether given node is declared directly inside a render property
150
+ * ```tsx
151
+ * const rows = { render: () => <div /> }
152
+ * ` ^^^^^^^^^^^^^ `
153
+ * _ = <Component rows={ [{ render: () => <div /> }] } />
154
+ * ` ^^^^^^^^^^^^^ `
155
+ * ```
156
+ * @internal
157
+ * @param node The AST node to check
158
+ * @returns `true` if component is declared inside a render property, `false` if not
159
+ */
160
+ declare function isDirectValueOfRenderPropertyLoose(node: TSESTree.Node): boolean;
161
+ /**
162
+ * Unsafe check whether given node is declared inside a render prop
163
+ * ```tsx
164
+ * _ = <Component renderRow={"node"} />
165
+ * ` ^^^^^^ `
166
+ * _ = <Component rows={ [{ render: "node" }] } />
167
+ * ` ^^^^^^ `
168
+ * ```
169
+ * @param node The AST node to check
170
+ * @returns `true` if component is declared inside a render prop, `false` if not
171
+ */
172
+ declare function isDeclaredInRenderPropLoose(node: TSESTree.Node): boolean;
111
173
  /**
112
174
  * Determine if a function node represents a valid React component definition
113
175
  *
@@ -404,72 +466,6 @@ declare function isComponentNameLoose(name: string): boolean;
404
466
  */
405
467
  declare function isFunctionWithLooseComponentName(context: RuleContext, fn: ast.TSESTreeFunction, allowNone?: boolean): boolean;
406
468
  //#endregion
407
- //#region src/component/component-render-method.d.ts
408
- /**
409
- * Check whether given node is a render method of a class component
410
- * @example
411
- * ```tsx
412
- * class Component extends React.Component {
413
- * renderHeader = () => <div />;
414
- * renderFooter = () => <div />;
415
- * }
416
- * ```
417
- * @param node The AST node to check
418
- * @returns `true` if node is a render function, `false` if not
419
- */
420
- declare function isRenderMethodLike(node: TSESTree.Node): node is ast.TSESTreeMethodOrProperty;
421
- //#endregion
422
- //#region src/component/component-render-prop.d.ts
423
- /**
424
- * Unsafe check whether given node is a render function
425
- * ```tsx
426
- * const renderRow = () => <div />
427
- * ` ^^^^^^^^^^^^`
428
- * _ = <Component renderRow={() => <div />} />
429
- * ` ^^^^^^^^^^^^^ `
430
- * ```
431
- * @param context The rule context
432
- * @param node The AST node to check
433
- * @returns `true` if node is a render function, `false` if not
434
- */
435
- declare function isRenderFunctionLoose(context: RuleContext, node: TSESTree.Node): node is ast.TSESTreeFunction;
436
- /**
437
- * Unsafe check whether given JSXAttribute is a render prop
438
- * ```tsx
439
- * _ = <Component renderRow={() => <div />} />
440
- * ` ^^^^^^^^^^^^^^^^^^^^^^^^^ `
441
- * ```
442
- * @param context The rule context
443
- * @param node The AST node to check
444
- * @returns `true` if node is a render prop, `false` if not
445
- */
446
- declare function isRenderPropLoose(context: RuleContext, node: TSESTree.JSXAttribute): boolean;
447
- /**
448
- * Unsafe check whether given node is declared directly inside a render property
449
- * ```tsx
450
- * const rows = { render: () => <div /> }
451
- * ` ^^^^^^^^^^^^^ `
452
- * _ = <Component rows={ [{ render: () => <div /> }] } />
453
- * ` ^^^^^^^^^^^^^ `
454
- * ```
455
- * @internal
456
- * @param node The AST node to check
457
- * @returns `true` if component is declared inside a render property, `false` if not
458
- */
459
- declare function isDirectValueOfRenderPropertyLoose(node: TSESTree.Node): boolean;
460
- /**
461
- * Unsafe check whether given node is declared inside a render prop
462
- * ```tsx
463
- * _ = <Component renderRow={"node"} />
464
- * ` ^^^^^^ `
465
- * _ = <Component rows={ [{ render: "node" }] } />
466
- * ` ^^^^^^ `
467
- * ```
468
- * @param node The AST node to check
469
- * @returns `true` if component is declared inside a render prop, `false` if not
470
- */
471
- declare function isDeclaredInRenderPropLoose(node: TSESTree.Node): boolean;
472
- //#endregion
473
469
  //#region src/component/component-wrapper.d.ts
474
470
  /**
475
471
  * Check if the node is a call expression for a component wrapper
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { findImportSource, findProperty, findVariable, getVariableDefinitionNode } from "@eslint-react/var";
1
+ import { findImportSource, findProperty, findVariable, getVariableInitializer } from "@eslint-react/var";
2
2
  import * as ast from "@eslint-react/ast";
3
3
  import { constFalse, constTrue, dual, flip, getOrElseUpdate, identity, unit } from "@eslint-react/eff";
4
4
  import { AST_NODE_TYPES } from "@typescript-eslint/types";
@@ -369,7 +369,7 @@ function getJsxAttribute(context, node, initialScope) {
369
369
  if (attr.type === AST_NODE_TYPES.JSXAttribute) return getJsxAttributeName(context, attr) === name;
370
370
  switch (attr.argument.type) {
371
371
  case AST_NODE_TYPES.Identifier: {
372
- const variableNode = getVariableDefinitionNode(findVariable(attr.argument.name, scope), 0);
372
+ const variableNode = getVariableInitializer(findVariable(attr.argument.name, scope), 0);
373
373
  if (variableNode?.type === AST_NODE_TYPES.ObjectExpression) return findProperty(name, variableNode.properties, scope) != null;
374
374
  return false;
375
375
  }
@@ -597,7 +597,7 @@ function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
597
597
  const { name } = node;
598
598
  if (name === "undefined") return !(hint & JsxDetectionHint.DoNotIncludeJsxWithUndefinedValue);
599
599
  if (ast.isJSXTagNameExpression(node)) return true;
600
- return isJsxLike(code, getVariableDefinitionNode(findVariable(name, code.getScope(node)), 0), hint);
600
+ return isJsxLike(code, getVariableInitializer(findVariable(name, code.getScope(node)), 0), hint);
601
601
  }
602
602
  }
603
603
  return false;
@@ -793,24 +793,6 @@ function isFunctionWithLooseComponentName(context, fn, allowNone = false) {
793
793
  return false;
794
794
  }
795
795
 
796
- //#endregion
797
- //#region src/component/component-render-method.ts
798
- /**
799
- * Check whether given node is a render method of a class component
800
- * @example
801
- * ```tsx
802
- * class Component extends React.Component {
803
- * renderHeader = () => <div />;
804
- * renderFooter = () => <div />;
805
- * }
806
- * ```
807
- * @param node The AST node to check
808
- * @returns `true` if node is a render function, `false` if not
809
- */
810
- function isRenderMethodLike(node) {
811
- return ast.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name.startsWith("render") && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
812
- }
813
-
814
796
  //#endregion
815
797
  //#region src/component/component-detection.ts
816
798
  /**
@@ -831,6 +813,21 @@ const ComponentDetectionHint = {
831
813
  */
832
814
  const DEFAULT_COMPONENT_DETECTION_HINT = 0n | ComponentDetectionHint.DoNotIncludeJsxWithBigIntValue | ComponentDetectionHint.DoNotIncludeJsxWithBooleanValue | ComponentDetectionHint.DoNotIncludeJsxWithNumberValue | ComponentDetectionHint.DoNotIncludeJsxWithStringValue | ComponentDetectionHint.DoNotIncludeJsxWithUndefinedValue | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayFlatMapCallback | ComponentDetectionHint.DoNotIncludeFunctionDefinedAsArrayMapCallback | ComponentDetectionHint.DoNotIncludeFunctionDefinedInArrayExpression | ComponentDetectionHint.DoNotIncludeFunctionDefinedInArrayPattern | ComponentDetectionHint.RequireAllArrayElementsToBeJsx | ComponentDetectionHint.RequireBothBranchesOfConditionalExpressionToBeJsx | ComponentDetectionHint.RequireBothSidesOfLogicalExpressionToBeJsx;
833
815
  /**
816
+ * Check whether given node is a render method of a class component
817
+ * @example
818
+ * ```tsx
819
+ * class Component extends React.Component {
820
+ * renderHeader = () => <div />;
821
+ * renderFooter = () => <div />;
822
+ * }
823
+ * ```
824
+ * @param node The AST node to check
825
+ * @returns `true` if node is a render function, `false` if not
826
+ */
827
+ function isRenderMethodLike(node) {
828
+ return ast.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name.startsWith("render") && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
829
+ }
830
+ /**
834
831
  * Check if the given node is a function within a render method of a class component
835
832
  *
836
833
  * @param node The AST node to check
@@ -849,6 +846,77 @@ function isRenderMethodCallback(node) {
849
846
  return greatGrandparent != null && isRenderMethodLike(parent) && isClassComponent(greatGrandparent);
850
847
  }
851
848
  /**
849
+ * Unsafe check whether given node is a render function
850
+ * ```tsx
851
+ * const renderRow = () => <div />
852
+ * ` ^^^^^^^^^^^^`
853
+ * _ = <Component renderRow={() => <div />} />
854
+ * ` ^^^^^^^^^^^^^ `
855
+ * ```
856
+ * @param context The rule context
857
+ * @param node The AST node to check
858
+ * @returns `true` if node is a render function, `false` if not
859
+ */
860
+ function isRenderFunctionLoose(context, node) {
861
+ if (!ast.isFunction(node)) return false;
862
+ const id = ast.getFunctionId(node);
863
+ switch (true) {
864
+ case id?.type === AST_NODE_TYPES.Identifier: return id.name.startsWith("render");
865
+ case id?.type === AST_NODE_TYPES.MemberExpression && id.property.type === AST_NODE_TYPES.Identifier: return id.property.name.startsWith("render");
866
+ case node.parent.type === AST_NODE_TYPES.JSXExpressionContainer && node.parent.parent.type === AST_NODE_TYPES.JSXAttribute && node.parent.parent.name.type === AST_NODE_TYPES.JSXIdentifier: return node.parent.parent.name.name.startsWith("render");
867
+ }
868
+ return false;
869
+ }
870
+ /**
871
+ * Unsafe check whether given JSXAttribute is a render prop
872
+ * ```tsx
873
+ * _ = <Component renderRow={() => <div />} />
874
+ * ` ^^^^^^^^^^^^^^^^^^^^^^^^^ `
875
+ * ```
876
+ * @param context The rule context
877
+ * @param node The AST node to check
878
+ * @returns `true` if node is a render prop, `false` if not
879
+ */
880
+ function isRenderPropLoose(context, node) {
881
+ if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) return false;
882
+ return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && isRenderFunctionLoose(context, node.value.expression);
883
+ }
884
+ /**
885
+ * Unsafe check whether given node is declared directly inside a render property
886
+ * ```tsx
887
+ * const rows = { render: () => <div /> }
888
+ * ` ^^^^^^^^^^^^^ `
889
+ * _ = <Component rows={ [{ render: () => <div /> }] } />
890
+ * ` ^^^^^^^^^^^^^ `
891
+ * ```
892
+ * @internal
893
+ * @param node The AST node to check
894
+ * @returns `true` if component is declared inside a render property, `false` if not
895
+ */
896
+ function isDirectValueOfRenderPropertyLoose(node) {
897
+ const matching = (node) => {
898
+ return node.type === AST_NODE_TYPES.Property && node.key.type === AST_NODE_TYPES.Identifier && node.key.name.startsWith("render");
899
+ };
900
+ return matching(node) || node.parent != null && matching(node.parent);
901
+ }
902
+ /**
903
+ * Unsafe check whether given node is declared inside a render prop
904
+ * ```tsx
905
+ * _ = <Component renderRow={"node"} />
906
+ * ` ^^^^^^ `
907
+ * _ = <Component rows={ [{ render: "node" }] } />
908
+ * ` ^^^^^^ `
909
+ * ```
910
+ * @param node The AST node to check
911
+ * @returns `true` if component is declared inside a render prop, `false` if not
912
+ */
913
+ function isDeclaredInRenderPropLoose(node) {
914
+ if (isDirectValueOfRenderPropertyLoose(node)) return true;
915
+ const parent = ast.findParentNode(node, ast.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
916
+ if (parent?.type !== AST_NODE_TYPES.JSXAttribute) return false;
917
+ return parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.name.name.startsWith("render");
918
+ }
919
+ /**
852
920
  * Check if a function node should be excluded based on provided detection hints
853
921
  *
854
922
  * @param node The function node to check
@@ -1132,80 +1200,6 @@ function isComponentWillUnmountCallback(node) {
1132
1200
  return ast.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
1133
1201
  }
1134
1202
 
1135
- //#endregion
1136
- //#region src/component/component-render-prop.ts
1137
- /**
1138
- * Unsafe check whether given node is a render function
1139
- * ```tsx
1140
- * const renderRow = () => <div />
1141
- * ` ^^^^^^^^^^^^`
1142
- * _ = <Component renderRow={() => <div />} />
1143
- * ` ^^^^^^^^^^^^^ `
1144
- * ```
1145
- * @param context The rule context
1146
- * @param node The AST node to check
1147
- * @returns `true` if node is a render function, `false` if not
1148
- */
1149
- function isRenderFunctionLoose(context, node) {
1150
- if (!ast.isFunction(node)) return false;
1151
- const id = ast.getFunctionId(node);
1152
- switch (true) {
1153
- case id?.type === AST_NODE_TYPES.Identifier: return id.name.startsWith("render");
1154
- case id?.type === AST_NODE_TYPES.MemberExpression && id.property.type === AST_NODE_TYPES.Identifier: return id.property.name.startsWith("render");
1155
- case node.parent.type === AST_NODE_TYPES.JSXExpressionContainer && node.parent.parent.type === AST_NODE_TYPES.JSXAttribute && node.parent.parent.name.type === AST_NODE_TYPES.JSXIdentifier: return node.parent.parent.name.name.startsWith("render");
1156
- }
1157
- return false;
1158
- }
1159
- /**
1160
- * Unsafe check whether given JSXAttribute is a render prop
1161
- * ```tsx
1162
- * _ = <Component renderRow={() => <div />} />
1163
- * ` ^^^^^^^^^^^^^^^^^^^^^^^^^ `
1164
- * ```
1165
- * @param context The rule context
1166
- * @param node The AST node to check
1167
- * @returns `true` if node is a render prop, `false` if not
1168
- */
1169
- function isRenderPropLoose(context, node) {
1170
- if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) return false;
1171
- return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && isRenderFunctionLoose(context, node.value.expression);
1172
- }
1173
- /**
1174
- * Unsafe check whether given node is declared directly inside a render property
1175
- * ```tsx
1176
- * const rows = { render: () => <div /> }
1177
- * ` ^^^^^^^^^^^^^ `
1178
- * _ = <Component rows={ [{ render: () => <div /> }] } />
1179
- * ` ^^^^^^^^^^^^^ `
1180
- * ```
1181
- * @internal
1182
- * @param node The AST node to check
1183
- * @returns `true` if component is declared inside a render property, `false` if not
1184
- */
1185
- function isDirectValueOfRenderPropertyLoose(node) {
1186
- const matching = (node) => {
1187
- return node.type === AST_NODE_TYPES.Property && node.key.type === AST_NODE_TYPES.Identifier && node.key.name.startsWith("render");
1188
- };
1189
- return matching(node) || node.parent != null && matching(node.parent);
1190
- }
1191
- /**
1192
- * Unsafe check whether given node is declared inside a render prop
1193
- * ```tsx
1194
- * _ = <Component renderRow={"node"} />
1195
- * ` ^^^^^^ `
1196
- * _ = <Component rows={ [{ render: "node" }] } />
1197
- * ` ^^^^^^ `
1198
- * ```
1199
- * @param node The AST node to check
1200
- * @returns `true` if component is declared inside a render prop, `false` if not
1201
- */
1202
- function isDeclaredInRenderPropLoose(node) {
1203
- if (isDirectValueOfRenderPropertyLoose(node)) return true;
1204
- const parent = ast.findParentNode(node, ast.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
1205
- if (parent?.type !== AST_NODE_TYPES.JSXAttribute) return false;
1206
- return parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.name.name.startsWith("render");
1207
- }
1208
-
1209
1203
  //#endregion
1210
1204
  //#region src/hierarchy/find-enclosing-component-or-hook.ts
1211
1205
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eslint-react/core",
3
- "version": "3.0.0-next.12",
3
+ "version": "3.0.0-next.14",
4
4
  "description": "ESLint React's ESLint utility module for static analysis of React core APIs and patterns.",
5
5
  "homepage": "https://github.com/Rel1cx/eslint-react",
6
6
  "bugs": {
@@ -34,10 +34,10 @@
34
34
  "@typescript-eslint/types": "canary",
35
35
  "@typescript-eslint/utils": "canary",
36
36
  "ts-pattern": "^5.9.0",
37
- "@eslint-react/ast": "3.0.0-next.12",
38
- "@eslint-react/eff": "3.0.0-next.12",
39
- "@eslint-react/var": "3.0.0-next.12",
40
- "@eslint-react/shared": "3.0.0-next.12"
37
+ "@eslint-react/ast": "3.0.0-next.14",
38
+ "@eslint-react/eff": "3.0.0-next.14",
39
+ "@eslint-react/shared": "3.0.0-next.14",
40
+ "@eslint-react/var": "3.0.0-next.14"
41
41
  },
42
42
  "devDependencies": {
43
43
  "tsdown": "^0.20.3",