@Contract(value = "null, _, _ -> null", pure = true)
  static ChainCallExtractor findExtractor(@Nullable PsiLambdaExpression lambda,
                                          @NotNull PsiExpression expression,
                                          @Nullable PsiType targetType) {
    if (lambda == null) return null;
    PsiParameterList parameters = lambda.getParameterList();
    if (parameters.getParametersCount() != 1) return null;
    PsiExpressionList args = tryCast(PsiUtil.skipParenthesizedExprUp(lambda.getParent()), PsiExpressionList.class);
    if (args == null || args.getExpressionCount() != 1) return null;
    PsiParameter parameter = parameters.getParameter(0);
    if (ExpressionUtils.isReferenceTo(expression, parameter) && parameter.getType().equals(targetType)) {
      // No-op extraction is useless
      return null;
    }
    PsiMethodCallExpression call = tryCast(args.getParent(), PsiMethodCallExpression.class);
    if (call == null) return null;
    for(ChainCallExtractor extractor : KEY.getExtensionList()) {
      if(extractor.canExtractChainCall(call, expression, targetType) &&
         StringUtil.isNotEmpty(extractor.getMethodName(parameter, expression, targetType))) {
        return extractor;
      }
    }
    return null;
  }
@Contract(value = "null, _, _ -> null", pure = true)
  static ChainCallExtractor findExtractor(@Nullable PsiLambdaExpression lambda,
                                          @NotNull PsiExpression expression,
                                          @Nullable PsiType targetType)