Skip to content

Commit

Permalink
fix: type inference on forwardRef components (#392)
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/__tests__/__snapshots__/main-test.js.snap
#	src/__tests__/main-test.js
#	src/handlers/flowTypeHandler.js
#	src/utils/getFlowTypeFromReactComponent.js
  • Loading branch information
jquense authored and danez committed Oct 16, 2019
1 parent 036be3d commit c4b3f54
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
6 changes: 5 additions & 1 deletion src/__tests__/__snapshots__/main-test.js.snap
Expand Up @@ -982,7 +982,11 @@ Object {
"props": Object {
"color": Object {
"description": "",
"required": true,
"flowType": Object {
"name": "string",
"nullable": true,
},
"required": false,
"type": Object {
"name": "string",
},
Expand Down
12 changes: 6 additions & 6 deletions src/__tests__/main-test.js
Expand Up @@ -52,7 +52,7 @@ describe('main', () => {

describe('React.createClass', () => {
test(`
var React = require("React");
var React = require("react");
var PropTypes = React.PropTypes;
var defaultProps = {
Expand Down Expand Up @@ -81,7 +81,7 @@ describe('main', () => {

describe('Class definition', () => {
test(`
const React = require("React");
const React = require("react");
const PropTypes = React.PropTypes;
const defaultProps = {
Expand All @@ -108,7 +108,7 @@ describe('main', () => {

describe('Stateless Component definition: ArrowFunctionExpression', () => {
test(`
import React, {PropTypes} from "React";
import React, {PropTypes} from "react";
const defaultProps = {
foo: true,
Expand All @@ -134,7 +134,7 @@ describe('main', () => {

describe('Stateless Component definition: FunctionDeclaration', () => {
test(`
import React, {PropTypes} from "React";
import React, {PropTypes} from "react";
const defaultProps = {
foo: true,
Expand Down Expand Up @@ -163,7 +163,7 @@ describe('main', () => {

describe('Stateless Component definition: FunctionExpression', () => {
test(`
import React, {PropTypes} from "React";
import React, {PropTypes} from "react";
const defaultProps = {
foo: true,
Expand Down Expand Up @@ -193,7 +193,7 @@ describe('main', () => {
describe('Stateless Component definition', () => {
it('is not so greedy', () => {
const source = `
import React, {PropTypes} from "React";
import React, {PropTypes} from "react";
/**
* Example component description
Expand Down
32 changes: 23 additions & 9 deletions src/utils/getFlowTypeFromReactComponent.js
Expand Up @@ -10,19 +10,29 @@
*
*/

import getTypeAnnotation from '../utils/getTypeAnnotation';
import getMemberValuePath from '../utils/getMemberValuePath';
import isReactComponentClass from '../utils/isReactComponentClass';
import isStatelessComponent from '../utils/isStatelessComponent';
import resolveGenericTypeAnnotation from '../utils/resolveGenericTypeAnnotation';
import getMemberValuePath from './getMemberValuePath';
import getTypeAnnotation from './getTypeAnnotation';
import isReactComponentClass from './isReactComponentClass';
import isReactForwardRefCall from './isReactForwardRefCall';
import resolveGenericTypeAnnotation from './resolveGenericTypeAnnotation';
import resolveToValue from './resolveToValue';

function getStatelessPropsPath(componentDefinition): NodePath {
const value = resolveToValue(componentDefinition);
if (isReactForwardRefCall(value)) {
const inner = value.get('arguments', 0);
return inner.get('params', 0);
}
return value.get('params', 0);
}

/**
* Given an React component (stateless or class) tries to find the
* flow type for the props. If not found or not one of the supported
* component types returns null.
*/
export default (path: NodePath): ?NodePath => {
let typePath: ?NodePath;
let typePath: ?NodePath = null;

if (isReactComponentClass(path)) {
const superTypes = path.get('superTypeParameters');
Expand All @@ -42,10 +52,14 @@ export default (path: NodePath): ?NodePath => {

typePath = getTypeAnnotation(propsMemberPath.parentPath);
}
} else if (isStatelessComponent(path)) {
const param = path.get('params').get(0);

typePath = getTypeAnnotation(param);
return typePath;
}

const propsParam = getStatelessPropsPath(path);

if (propsParam) {
typePath = getTypeAnnotation(propsParam);
}

return typePath;
Expand Down

0 comments on commit c4b3f54

Please sign in to comment.