Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Feb 22, 2022
1 parent f51ec45 commit 4db87c1
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 52 deletions.
9 changes: 7 additions & 2 deletions lib/rules/display-name.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const astUtil = require('../util/ast');
const docsUrl = require('../util/docsUrl');
const propsUtil = require('../util/props');
const report = require('../util/report');
const testReactVersion = require('../util/version').testReactVersion;

// ------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -47,6 +48,8 @@ module.exports = {
const config = context.options[0] || {};
const ignoreTranspilerName = config.ignoreTranspilerName || false;

const hasDisplayNameBug = !testReactVersion(context, '^0.14.10 || ^15.7.0 || >=16.12.0');

/**
* Mark a prop type as declared
* @param {ASTNode} node The AST node being checked.
Expand Down Expand Up @@ -214,13 +217,14 @@ module.exports = {
}

if (node.arguments.length > 0 && astUtil.isFunctionLikeExpression(node.arguments[0])) {
// Skip over React.forwardRef declarations that are embeded within
// Skip over React.forwardRef declarations that are embedded within
// a React.memo i.e. React.memo(React.forwardRef(/* ... */))
// This means that we raise a single error for the call to React.memo
// instead of one for React.memo and one for React.forwardRef
const isWrappedInAnotherPragma = utils.getPragmaComponentWrapper(node);
if (
!isWrappedInAnotherPragma
!hasDisplayNameBug
&& !isWrappedInAnotherPragma
&& (ignoreTranspilerName || !hasTranspilerName(node.arguments[0]))
) {
return;
Expand All @@ -236,6 +240,7 @@ module.exports = {
const list = components.list();
// Report missing display name for all components
values(list).filter((component) => !component.hasDisplayName).forEach((component) => {
console.log({ component });
reportMissingDisplayName(component);
});
},
Expand Down
157 changes: 107 additions & 50 deletions tests/lib/rules/display-name.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// ------------------------------------------------------------------------------

const RuleTester = require('eslint').RuleTester;
const flatMap = require('array.prototype.flatmap');
const rule = require('../../../lib/rules/display-name');

const parsers = require('../../helpers/parsers');
Expand All @@ -28,7 +29,7 @@ const parserOptions = {

const ruleTester = new RuleTester({ parserOptions });
ruleTester.run('display-name', rule, {
valid: parsers.all([
valid: parsers.all([].concat(
{
code: `
var Hello = createReactClass({
Expand Down Expand Up @@ -579,9 +580,26 @@ ruleTester.run('display-name', rule, {
}
`,
},
]),
flatMap(['0.14.10', '15.7.0', '16.12.0'], (version) => [
{
// React does not handle the result of forwardRef being passed into memo
// ComponentWithMemoAndForwardRef gets shown as Memo(Anonymous)
// See https://github.com/facebook/react/issues/16722
code: `
import React from 'react'
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(function ComponentLike({ world }, ref) {
return <div ref={ref}>Hello {world}</div>
})
)
`,
settings: { react: { version } },
},
])
)),

invalid: parsers.all([
invalid: parsers.all([].concat(
{
code: `
var Hello = createReactClass({
Expand All @@ -591,10 +609,7 @@ ruleTester.run('display-name', rule, {
});
`,
options: [{ ignoreTranspilerName: true }],
errors: [
{
messageId: 'noDisplayName',
}],
errors: [{ messageId: 'noDisplayName' }],
},
{
code: `
Expand Down Expand Up @@ -800,50 +815,92 @@ ruleTester.run('display-name', rule, {
`,
errors: [{ messageId: 'noDisplayName' }],
},
{
// Only trigger an error for the outer React.memo
code: `
import React from 'react'
flatMap(['0.14.9', '15.6.999', '16.11.999'], (version) => [
{
// Only trigger an error for the outer React.memo
code: `
import React from 'react'
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(({ world }, ref) => {
return <div ref={ref}>Hello {world}</div>
})
)
`,
errors: [
{
messageId: 'noDisplayName',
}],
},
{
// Only trigger an error for the outer React.memo
code: `
import React from 'react'
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(function({ world }, ref) {
return <div ref={ref}>Hello {world}</div>
})
)
`,
errors: [{ messageId: 'noDisplayName' }],
},
{
// React does not handle the result of forwardRef being passed into memo
// ComponentWithMemoAndForwardRef gets shown as Memo(Anonymous)
// See https://github.com/facebook/react/issues/16722
code: `
import React from 'react'
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(({ world }, ref) => {
return <div ref={ref}>Hello {world}</div>
})
)
`,
settings: { react: { version } },
errors: [
{ messageId: 'noDisplayName', line: 4 },
],
},
{
// Only trigger an error for the outer React.memo
code: `
import React from 'react'
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(function ComponentLike({ world }, ref) {
return <div ref={ref}>Hello {world}</div>
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(function({ world }, ref) {
return <div ref={ref}>Hello {world}</div>
})
)
`,
errors: [{ messageId: 'noDisplayName' }],
},
)
`,
settings: { react: { version } },
errors: [
{ messageId: 'noDisplayName', line: 4 },
],
},
{
// React does not handle the result of forwardRef being passed into memo
// ComponentWithMemoAndForwardRef gets shown as Memo(Anonymous)
// See https://github.com/facebook/react/issues/16722
code: `
import React from 'react'
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(function ComponentLike({ world }, ref) {
return <div ref={ref}>Hello {world}</div>
})
)
`,
settings: { react: { version } },
errors: [
{ messageId: 'noDisplayName', line: 4 },
],
},
]),
flatMap(['0.14.10', '15.7.0', '16.12.0'], (version) => [
{
// Only trigger an error for the outer React.memo
code: `
import React from 'react'
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(({ world }, ref) => {
return <div ref={ref}>Hello {world}</div>
})
)
`,
settings: { react: { version } },
errors: [
{ messageId: 'noDisplayName', line: 4 },
],
},
{
// Only trigger an error for the outer React.memo
code: `
import React from 'react'
const MemoizedForwardRefComponentLike = React.memo(
React.forwardRef(function({ world }, ref) {
return <div ref={ref}>Hello {world}</div>
})
)
`,
settings: { react: { version } },
errors: [
{ messageId: 'noDisplayName', line: 4 },
],
},
]),
{
code: `
import React from "react";
Expand Down Expand Up @@ -984,6 +1041,6 @@ ruleTester.run('display-name', rule, {
line: 9,
},
],
},
]),
}
)),
});

0 comments on commit 4db87c1

Please sign in to comment.