NotNull
  public PsiClass createBuilderClass(@NotNull PsiClass psiClass, @Nullable PsiMethod psiMethod, @NotNull PsiAnnotation psiAnnotation) {
    final LombokLightClassBuilder builderClass;
    if (null != psiMethod) {
      builderClass = createEmptyBuilderClass(psiClass, psiMethod, psiAnnotation);
    }
    else {
      builderClass = createEmptyBuilderClass(psiClass, psiAnnotation);
    }

    if (hasValidJacksonizedAnnotation(psiClass, psiMethod)) {
      handleJacksonized(psiClass, psiMethod, psiAnnotation, builderClass);
    }

    builderClass.withFieldSupplier((thisPsiClass) -> {
      final List<BuilderInfo> builderInfos = createBuilderInfos(psiAnnotation, psiClass, psiMethod, thisPsiClass);
      // create builder Fields
      return builderInfos.stream()
        .map(BuilderInfo::renderBuilderFields)
        .flatMap(Collection::stream)
        .collect(Collectors.toList());
    });

    builderClass.withMethodSupplier((thisPsiClass) -> {
      Collection<PsiMethod> psiMethods = new ArrayList<>(createConstructors(thisPsiClass, psiAnnotation));

      final List<BuilderInfo> builderInfos = createBuilderInfos(psiAnnotation, psiClass, psiMethod, thisPsiClass);
      // create builder methods
      for (BuilderInfo info : builderInfos) {
        psiMethods.addAll(info.renderBuilderMethods(Collections.emptyMap()));
      }

      // create 'build' method
      final String buildMethodName = getBuildMethodName(psiAnnotation);
      psiMethods.add(createBuildMethod(psiAnnotation, psiClass, psiMethod, thisPsiClass, buildMethodName, builderInfos));

      // create 'toString' method
      psiMethods.add(createToStringMethod(psiAnnotation, thisPsiClass));

      return psiMethods;
    });

    return builderClass;
  }

NotNull
  public PsiClass createBuilderClass(@NotNull PsiClass psiClass, @Nullable PsiMethod psiMethod, @NotNull PsiAnnotation psiAnnotation) 