Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@arthurgeron/eslint-plugin-react-usememo

Package Overview
Dependencies
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arthurgeron/eslint-plugin-react-usememo - npm Package Compare versions

Comparing version 0.1.1 to 0.1.2

170

dist/index.js

@@ -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 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc