isReactComponentClass.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import isReactModuleName from './isReactModuleName.js';
  2. import resolveToModule from './resolveToModule.js';
  3. import resolveToValue from './resolveToValue.js';
  4. import isDestructuringAssignment from './isDestructuringAssignment.js';
  5. import isImportSpecifier from './isImportSpecifier.js';
  6. function isRenderMethod(path) {
  7. if ((!path.isClassMethod() || path.node.kind !== 'method') &&
  8. !path.isClassProperty()) {
  9. return false;
  10. }
  11. if (path.node.computed || path.node.static) {
  12. return false;
  13. }
  14. const key = path.get('key');
  15. if (!key.isIdentifier() || key.node.name !== 'render') {
  16. return false;
  17. }
  18. return true;
  19. }
  20. function classExtendsReactComponent(path) {
  21. if (path.isMemberExpression()) {
  22. const property = path.get('property');
  23. if (property.isIdentifier({ name: 'Component' }) ||
  24. property.isIdentifier({ name: 'PureComponent' })) {
  25. return true;
  26. }
  27. }
  28. else if (isImportSpecifier(path, 'Component') ||
  29. isImportSpecifier(path, 'PureComponent')) {
  30. return true;
  31. }
  32. else if (isDestructuringAssignment(path, 'Component') ||
  33. isDestructuringAssignment(path, 'PureComponent')) {
  34. return true;
  35. }
  36. return false;
  37. }
  38. /**
  39. * Returns `true` of the path represents a class definition which either extends
  40. * `React.Component` or has a superclass and implements a `render()` method.
  41. */
  42. export default function isReactComponentClass(path) {
  43. if (!path.isClass()) {
  44. return false;
  45. }
  46. // React.Component or React.PureComponent
  47. const superClass = path.get('superClass');
  48. if (superClass.hasNode()) {
  49. const resolvedSuperClass = resolveToValue(superClass);
  50. if (classExtendsReactComponent(resolvedSuperClass)) {
  51. const module = resolveToModule(resolvedSuperClass);
  52. if (module && isReactModuleName(module)) {
  53. return true;
  54. }
  55. }
  56. }
  57. else {
  58. // does not extend anything
  59. return false;
  60. }
  61. // render method
  62. if (path.get('body').get('body').some(isRenderMethod)) {
  63. return true;
  64. }
  65. return false;
  66. }