Skip to content

Commit

Permalink
Assume HOC first param is Component not last (#343)
Browse files Browse the repository at this point in the history
Unless we know for sure it is not a component (literal, array, object, spread)
  • Loading branch information
danez committed Oct 16, 2019
1 parent a1f9b9a commit 2873c8d
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 17 deletions.
53 changes: 39 additions & 14 deletions src/utils/__tests__/resolveHOC-test.js
Expand Up @@ -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', () => {
Expand Down
20 changes: 17 additions & 3 deletions src/utils/resolveHOC.js
Expand Up @@ -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));
}
}

Expand Down

0 comments on commit 2873c8d

Please sign in to comment.