From 2873c8d8e2ae37f18479b3b6b3fc06b13bf78367 Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Wed, 16 Oct 2019 23:57:16 +0200 Subject: [PATCH] Assume HOC first param is Component not last (#343) Unless we know for sure it is not a component (literal, array, object, spread) --- src/utils/__tests__/resolveHOC-test.js | 53 +++++++++++++++++++------- src/utils/resolveHOC.js | 20 ++++++++-- 2 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/utils/__tests__/resolveHOC-test.js b/src/utils/__tests__/resolveHOC-test.js index 70b9749f22f..d13b3b9d154 100644 --- a/src/utils/__tests__/resolveHOC-test.js +++ b/src/utils/__tests__/resolveHOC-test.js @@ -19,33 +19,58 @@ describe('resolveHOC', () => { } it('resolves simple hoc', () => { - const path = parse(['hoc(42);'].join('\n')); - expect(resolveHOC(path)).toEqualASTNode(builders.literal(42)); + const path = parse(['hoc(Component);'].join('\n')); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); }); it('resolves simple hoc w/ multiple args', () => { - const path = parse(['hoc1(arg1a, arg1b)(42);'].join('\n')); - expect(resolveHOC(path)).toEqualASTNode(builders.literal(42)); + const path = parse(['hoc1(arg1a, arg1b)(Component);'].join('\n')); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); }); it('resolves nested hocs', () => { const path = parse( - ['hoc2(arg2b, arg2b)(', ' hoc1(arg1a, arg2a)(42)', ');'].join('\n'), + `hoc2(arg2b, arg2b)( + hoc1(arg1a, arg2a)(Component) + );`, ); - expect(resolveHOC(path)).toEqualASTNode(builders.literal(42)); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); }); it('resolves really nested hocs', () => { const path = parse( - [ - 'hoc3(arg3a, arg3b)(', - ' hoc2(arg2b, arg2b)(', - ' hoc1(arg1a, arg2a)(42)', - ' )', - ');', - ].join('\n'), + `hoc3(arg3a, arg3b)( + hoc2(arg2b, arg2b)( + hoc1(arg1a, arg2a)(Component) + ) + );`, ); - expect(resolveHOC(path)).toEqualASTNode(builders.literal(42)); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); + }); + + it('resolves HOC with additional params', () => { + const path = parse(`hoc3(Component, {})`); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); + }); + + it('resolves HOC as last element if first is literal', () => { + const path = parse(`hoc3(41, Component)`); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); + }); + + it('resolves HOC as last element if first is array', () => { + const path = parse(`hoc3([], Component)`); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); + }); + + it('resolves HOC as last element if first is object', () => { + const path = parse(`hoc3({}, Component)`); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); + }); + + it('resolves HOC as last element if first is spread', () => { + const path = parse(`hoc3(...params, Component)`); + expect(resolveHOC(path)).toEqualASTNode(builders.identifier('Component')); }); it('resolves intermediate hocs', () => { diff --git a/src/utils/resolveHOC.js b/src/utils/resolveHOC.js index a5ff025e11b..35bdb3a8338 100644 --- a/src/utils/resolveHOC.js +++ b/src/utils/resolveHOC.js @@ -28,9 +28,23 @@ export default function resolveHOC(path: NodePath): NodePath { !isReactForwardRefCall(path) ) { if (node.arguments.length) { - return resolveHOC( - resolveToValue(path.get('arguments', node.arguments.length - 1)), - ); + const inner = path.get('arguments', 0); + + // If the first argument is one of these types then the component might be the last argument + // If there are all identifiers then we cannot figure out exactly and have to assume it is the first + if ( + node.arguments.length > 1 && + (t.Literal.check(inner.node) || + t.ObjectExpression.check(inner.node) || + t.ArrayExpression.check(inner.node) || + t.SpreadElement.check(inner.node)) + ) { + return resolveHOC( + resolveToValue(path.get('arguments', node.arguments.length - 1)), + ); + } + + return resolveHOC(resolveToValue(inner)); } }