@arthurgeron/eslint-plugin-react-usememo
Advanced tools
Comparing version 0.1.1 to 0.1.2
@@ -27,3 +27,86 @@ 'use strict'; | ||
var componentNameRegex$1 = /^[^a-z]/; | ||
var componentNameRegex = /^[^a-z]/; | ||
function isComplexComponent(node) { | ||
if (node.type !== "JSXOpeningElement") | ||
return false; | ||
if (node.name.type !== "JSXIdentifier") | ||
return false; | ||
return componentNameRegex.test(node.name.name); | ||
} | ||
var MemoStatus; | ||
(function (MemoStatus) { | ||
MemoStatus[MemoStatus["Memoized"] = 0] = "Memoized"; | ||
MemoStatus[MemoStatus["UnmemoizedObject"] = 1] = "UnmemoizedObject"; | ||
MemoStatus[MemoStatus["UnmemoizedArray"] = 2] = "UnmemoizedArray"; | ||
MemoStatus[MemoStatus["UnmemoizedNew"] = 3] = "UnmemoizedNew"; | ||
MemoStatus[MemoStatus["UnmemoizedFunction"] = 4] = "UnmemoizedFunction"; | ||
MemoStatus[MemoStatus["UnmemoizedFunctionCall"] = 5] = "UnmemoizedFunctionCall"; | ||
MemoStatus[MemoStatus["UnmemoizedJSX"] = 6] = "UnmemoizedJSX"; | ||
MemoStatus[MemoStatus["UnmemoizedOther"] = 7] = "UnmemoizedOther"; | ||
})(MemoStatus || (MemoStatus = {})); | ||
function isComponentName(name) { | ||
var _a; | ||
// All components are PascalCased, thoroughly checking for this only adds processing time and opens more chance to bugs/issues. | ||
return (name === null || name === void 0 ? void 0 : name[0]) === ((_a = name === null || name === void 0 ? void 0 : name[0]) === null || _a === void 0 ? void 0 : _a.toUpperCase()); | ||
} | ||
function isCallExpression(node, name) { | ||
if (node.callee.type === "MemberExpression") { | ||
var _a = node.callee, object = _a.object, property = _a.property; | ||
if (object.type === "Identifier" && | ||
property.type === "Identifier" && | ||
object.name === "React" && | ||
property.name === name) { | ||
return true; | ||
} | ||
} | ||
else if (node.callee.type === "Identifier" && node.callee.name === name) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function getIdentifierMemoStatus(context, _a) { | ||
var name = _a.name; | ||
var variable = context.getScope().variables.find(function (v) { return v.name === name; }); | ||
if (variable === undefined) | ||
return MemoStatus.Memoized; | ||
var node = variable.defs[0].node; | ||
if (node.type !== "VariableDeclarator") | ||
return MemoStatus.Memoized; | ||
if (node.parent.kind === "let") { | ||
context.report({ node: node, messageId: "usememo-const" }); | ||
if (!node.init) { | ||
// Rely on usememo-const reported error to fail this identifier | ||
return MemoStatus.Memoized; | ||
} | ||
} | ||
return getExpressionMemoStatus(context, node.init); | ||
} | ||
function getExpressionMemoStatus(context, expression) { | ||
switch (expression.type) { | ||
case "ObjectExpression": | ||
return MemoStatus.UnmemoizedObject; | ||
case "ArrayExpression": | ||
return MemoStatus.UnmemoizedArray; | ||
case "NewExpression": | ||
return MemoStatus.UnmemoizedNew; | ||
case "FunctionExpression": | ||
case "ArrowFunctionExpression": | ||
return MemoStatus.UnmemoizedFunction; | ||
case "JSXElement": | ||
return MemoStatus.UnmemoizedJSX; | ||
case "CallExpression": | ||
if (isCallExpression(expression, "useMemo") || | ||
isCallExpression(expression, "useCallback")) { | ||
return MemoStatus.Memoized; | ||
} | ||
return MemoStatus.UnmemoizedFunctionCall; | ||
case "Identifier": | ||
return getIdentifierMemoStatus(context, expression); | ||
case "BinaryExpression": | ||
return MemoStatus.Memoized; | ||
default: | ||
return MemoStatus.UnmemoizedOther; | ||
} | ||
} | ||
function isMemoCallExpression(node) { | ||
@@ -57,3 +140,3 @@ if (node.type !== "CallExpression") | ||
if (id.type === "Identifier") { | ||
if (componentNameRegex$1.test(id.name)) { | ||
if (isComponentName(id === null || id === void 0 ? void 0 : id.name)) { | ||
context.report({ node: node, messageId: "memo-required" }); | ||
@@ -65,3 +148,3 @@ } | ||
currentNode.type === "Program") { | ||
if (node.id !== null && componentNameRegex$1.test(node.id.name)) { | ||
if (node.id !== null && isComponentName(node.id.name)) { | ||
context.report({ node: node, messageId: "memo-required" }); | ||
@@ -73,3 +156,3 @@ } | ||
var filename = path__namespace.basename(context.getFilename()); | ||
if (componentNameRegex$1.test(filename)) { | ||
if (isComponentName(filename)) { | ||
context.report({ node: node, messageId: "memo-required" }); | ||
@@ -137,81 +220,2 @@ } | ||
var componentNameRegex = /^[^a-z]/; | ||
function isComplexComponent(node) { | ||
if (node.type !== "JSXOpeningElement") | ||
return false; | ||
if (node.name.type !== "JSXIdentifier") | ||
return false; | ||
return componentNameRegex.test(node.name.name); | ||
} | ||
var MemoStatus; | ||
(function (MemoStatus) { | ||
MemoStatus[MemoStatus["Memoized"] = 0] = "Memoized"; | ||
MemoStatus[MemoStatus["UnmemoizedObject"] = 1] = "UnmemoizedObject"; | ||
MemoStatus[MemoStatus["UnmemoizedArray"] = 2] = "UnmemoizedArray"; | ||
MemoStatus[MemoStatus["UnmemoizedNew"] = 3] = "UnmemoizedNew"; | ||
MemoStatus[MemoStatus["UnmemoizedFunction"] = 4] = "UnmemoizedFunction"; | ||
MemoStatus[MemoStatus["UnmemoizedFunctionCall"] = 5] = "UnmemoizedFunctionCall"; | ||
MemoStatus[MemoStatus["UnmemoizedJSX"] = 6] = "UnmemoizedJSX"; | ||
MemoStatus[MemoStatus["UnmemoizedOther"] = 7] = "UnmemoizedOther"; | ||
})(MemoStatus || (MemoStatus = {})); | ||
function isCallExpression(node, name) { | ||
if (node.callee.type === "MemberExpression") { | ||
var _a = node.callee, object = _a.object, property = _a.property; | ||
if (object.type === "Identifier" && | ||
property.type === "Identifier" && | ||
object.name === "React" && | ||
property.name === name) { | ||
return true; | ||
} | ||
} | ||
else if (node.callee.type === "Identifier" && node.callee.name === name) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function getIdentifierMemoStatus(context, _a) { | ||
var name = _a.name; | ||
var variable = context.getScope().variables.find(function (v) { return v.name === name; }); | ||
if (variable === undefined) | ||
return MemoStatus.Memoized; | ||
var node = variable.defs[0].node; | ||
if (node.type !== "VariableDeclarator") | ||
return MemoStatus.Memoized; | ||
if (node.parent.kind === "let") { | ||
context.report({ node: node, messageId: "usememo-const" }); | ||
if (!node.init) { | ||
// Rely on usememo-const reported error to fail this identifier | ||
return MemoStatus.Memoized; | ||
} | ||
} | ||
return getExpressionMemoStatus(context, node.init); | ||
} | ||
function getExpressionMemoStatus(context, expression) { | ||
switch (expression.type) { | ||
case "ObjectExpression": | ||
return MemoStatus.UnmemoizedObject; | ||
case "ArrayExpression": | ||
return MemoStatus.UnmemoizedArray; | ||
case "NewExpression": | ||
return MemoStatus.UnmemoizedNew; | ||
case "FunctionExpression": | ||
case "ArrowFunctionExpression": | ||
return MemoStatus.UnmemoizedFunction; | ||
case "JSXElement": | ||
return MemoStatus.UnmemoizedJSX; | ||
case "CallExpression": | ||
if (isCallExpression(expression, "useMemo") || | ||
isCallExpression(expression, "useCallback")) { | ||
return MemoStatus.Memoized; | ||
} | ||
return MemoStatus.UnmemoizedFunctionCall; | ||
case "Identifier": | ||
return getIdentifierMemoStatus(context, expression); | ||
case "BinaryExpression": | ||
return MemoStatus.Memoized; | ||
default: | ||
return MemoStatus.UnmemoizedOther; | ||
} | ||
} | ||
function isHook(node) { | ||
@@ -218,0 +222,0 @@ if (node.type === "Identifier") { |
{ | ||
"name": "@arthurgeron/eslint-plugin-react-usememo", | ||
"version": "0.1.1", | ||
"version": "0.1.2", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -6,3 +6,2 @@ # eslint-plugin-react-usememo | ||
## Rationale | ||
[Why we memo all the things](https://attardi.org/why-we-memo-all-the-things/). | ||
React Native's own [docs](https://reactnative.dev/docs/0.61/optimizing-flatlist-configuration#avoid-anonymous-function-on-renderitem) state how it's important to use static or memoized as props for complex children (FlatList on that case), that applies even more broadly when we are talking about custom components (the Components you've created), it might not seem necessary at first but you'll be making a bet that the component in question will never grow to use `memo` or those props in hooks (i.e. useEffect, useMemo, useCallback), you'll only notice once your solution starts freezing and dropping frames, that's why using the `require-usememo` rule is recommended. | ||
@@ -9,0 +8,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
26910
411
217