function resolvesToJSXElementOrReactCall()

in src/utils/isStatelessComponent.ts [32:143]


function resolvesToJSXElementOrReactCall(
  path: NodePath,
  importer: Importer,
  seen: WeakSet<NodePath>,
): boolean {
  // avoid returns with recursive function calls
  if (seen.has(path)) {
    return false;
  }

  seen.add(path);

  // Is the path is already a JSX element or a call to one of the React.* functions
  if (isJSXElementOrReactCall(path, importer)) {
    return true;
  }

  const resolvedPath = resolveToValue(path, importer);

  // If the path points to a conditional expression, then we need to look only at
  // the two possible paths
  if (resolvedPath.node.type === 'ConditionalExpression') {
    return (
      resolvesToJSXElementOrReactCall(
        resolvedPath.get('consequent'),
        importer,
        seen,
      ) ||
      resolvesToJSXElementOrReactCall(
        resolvedPath.get('alternate'),
        importer,
        seen,
      )
    );
  }

  // If the path points to a logical expression (AND, OR, ...), then we need to look only at
  // the two possible paths
  if (resolvedPath.node.type === 'LogicalExpression') {
    return (
      resolvesToJSXElementOrReactCall(
        resolvedPath.get('left'),
        importer,
        seen,
      ) ||
      resolvesToJSXElementOrReactCall(resolvedPath.get('right'), importer, seen)
    );
  }

  // Is the resolved path is already a JSX element or a call to one of the React.* functions
  // Only do this if the resolvedPath actually resolved something as otherwise we did this check already
  if (
    resolvedPath !== path &&
    isJSXElementOrReactCall(resolvedPath, importer)
  ) {
    return true;
  }

  // If we have a call expression, lets try to follow it
  if (resolvedPath.node.type === 'CallExpression') {
    let calleeValue = resolveToValue(resolvedPath.get('callee'), importer);

    if (returnsJSXElementOrReactCall(calleeValue, importer, seen)) {
      return true;
    }

    let resolvedValue;

    const namesToResolve = [calleeValue.get('property')];

    if (calleeValue.node.type === 'MemberExpression') {
      if (calleeValue.get('object').node.type === 'Identifier') {
        resolvedValue = resolveToValue(calleeValue.get('object'), importer);
      } else if (t.MemberExpression.check(calleeValue.node)) {
        do {
          calleeValue = calleeValue.get('object');
          namesToResolve.unshift(calleeValue.get('property'));
        } while (t.MemberExpression.check(calleeValue.node));

        resolvedValue = resolveToValue(calleeValue.get('object'), importer);
      }
    }

    if (resolvedValue && t.ObjectExpression.check(resolvedValue.node)) {
      const resolvedMemberExpression = namesToResolve.reduce(
        (result, nodePath) => {
          if (!nodePath) {
            return result;
          }

          if (result) {
            result = getPropertyValuePath(result, nodePath.node.name, importer);
            if (result && t.Identifier.check(result.node)) {
              return resolveToValue(result, importer);
            }
          }
          return result;
        },
        resolvedValue,
      );

      if (
        !resolvedMemberExpression ||
        returnsJSXElementOrReactCall(resolvedMemberExpression, importer, seen)
      ) {
        return true;
      }
    }
  }

  return false;
}