Skip to content

Commit

Permalink
Fix detecting super class in react class components
Browse files Browse the repository at this point in the history
  • Loading branch information
danez committed Sep 17, 2023
1 parent 82154c3 commit c01d1a0
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 16 deletions.
6 changes: 6 additions & 0 deletions .changeset/eight-coats-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'react-docgen': patch
---

Fix detection of react class components when super class is imported via named
import.
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,25 @@ describe('isReactComponentClass', () => {
});

test('ignores static render methods', () => {
const def = parse.statement('class Foo { static render() {}}');
const def = parse.statement('class Foo extends X { static render() {}}');

expect(isReactComponentClass(def)).toBe(false);
});

test('ignores dynamic render methods', () => {
const def = parse.statement('class Foo { static [render]() {}}');
const def = parse.statement(
'class Foo extends X { static [render]() {}}',
);

expect(isReactComponentClass(def)).toBe(false);
});

test('ignores getter or setter render methods', () => {
let def = parse.statement('class Foo { get render() {}}');
let def = parse.statement('class Foo extends X { get render() {}}');

expect(isReactComponentClass(def)).toBe(false);

def = parse.statement('class Foo { set render(value) {}}');
def = parse.statement('class Foo extends X { set render(value) {}}');
expect(isReactComponentClass(def)).toBe(false);
});
});
Expand Down Expand Up @@ -86,6 +88,33 @@ describe('isReactComponentClass', () => {
expect(isReactComponentClass(def)).toBe(true);
});

test('resolves the super class reference with named import', () => {
const def = parse.statementLast(`
import { Component } from 'react';
class Foo extends Component {}
`);

expect(isReactComponentClass(def)).toBe(true);
});

test('resolves the super class reference with default import', () => {
const def = parse.statementLast(`
import React from 'react';
class Foo extends React.Component {}
`);

expect(isReactComponentClass(def)).toBe(true);
});

test('resolves the super class reference with namespace import', () => {
const def = parse.statementLast(`
import * as React from 'react';
class Foo extends React.Component {}
`);

expect(isReactComponentClass(def)).toBe(true);
});

test('resolves the super class reference with alias', () => {
const def = parse.statementLast(`
var { Component: C } = require('react');
Expand Down
28 changes: 16 additions & 12 deletions packages/react-docgen/src/utils/isReactComponentClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import isReactModuleName from './isReactModuleName.js';
import resolveToModule from './resolveToModule.js';
import resolveToValue from './resolveToValue.js';
import isDestructuringAssignment from './isDestructuringAssignment.js';
import isImportSpecifier from './isImportSpecifier.js';

function isRenderMethod(path: NodePath): boolean {
if (
Expand Down Expand Up @@ -35,19 +36,24 @@ function classExtendsReactComponent(path: NodePath): boolean {
const property = path.get('property');

if (
!property.isIdentifier({ name: 'Component' }) &&
!property.isIdentifier({ name: 'PureComponent' })
property.isIdentifier({ name: 'Component' }) ||
property.isIdentifier({ name: 'PureComponent' })
) {
return false;
return true;
}
} else if (
!isDestructuringAssignment(path, 'Component') &&
!isDestructuringAssignment(path, 'PureComponent')
isImportSpecifier(path, 'Component') ||
isImportSpecifier(path, 'PureComponent')
) {
return false;
return true;
} else if (
isDestructuringAssignment(path, 'Component') ||
isDestructuringAssignment(path, 'PureComponent')
) {
return true;
}

return true;
return false;
}

/**
Expand All @@ -61,11 +67,6 @@ export default function isReactComponentClass(
return false;
}

// extends something
if (!path.node.superClass) {
return false;
}

// React.Component or React.PureComponent
const superClass = path.get('superClass');

Expand All @@ -79,6 +80,9 @@ export default function isReactComponentClass(
return true;
}
}
} else {
// does not extend anything
return false;
}

// render method
Expand Down

0 comments on commit c01d1a0

Please sign in to comment.