Optional<PsiMethod> (@NotNull PsiClass containingClass, @Nullable PsiMethod psiMethod, @NotNull PsiClass builderPsiClass, @NotNull PsiAnnotation psiAnnotation) { if (!PsiAnnotationUtil.getBooleanAnnotationValue(psiAnnotation, TO_BUILDER_ANNOTATION_KEY, false)) { return Optional.empty(); } final List<BuilderInfo> builderInfos = createBuilderInfos(psiAnnotation, containingClass, psiMethod, builderPsiClass); builderInfos.forEach(BuilderInfo::withObtainVia); final PsiType psiTypeWithGenerics; if (null != psiMethod) { psiTypeWithGenerics = calculateResultType(builderInfos, builderPsiClass, containingClass); } else { psiTypeWithGenerics = PsiClassUtil.getTypeWithGenerics(builderPsiClass); } final LombokLightMethodBuilder methodBuilder = new LombokLightMethodBuilder(containingClass.getManager(), TO_BUILDER_METHOD_NAME) .withMethodReturnType(psiTypeWithGenerics) .withContainingClass(containingClass) .withNavigationElement(psiAnnotation) .withModifier(getBuilderOuterAccessVisibility(psiAnnotation)); final String toBuilderPrependStatements = builderInfos.stream() .map(BuilderInfo::renderToBuilderPrependStatement) .filter(Predicate.not(StringUtil::isEmpty)) .collect(Collectors.joining("\n")); final String toBuilderMethodCalls = builderInfos.stream() .map(BuilderInfo::renderToBuilderCallWithPrependLogic) .filter(Predicate.not(StringUtil::isEmpty)) .collect(Collectors.joining(".", ".", "")); final String toBuilderAppendStatements = builderInfos.stream() .map(BuilderInfo::renderToBuilderAppendStatement) .filter(Predicate.not(StringUtil::isEmpty)) .collect(Collectors.joining("\n")); final String canonicalText = psiTypeWithGenerics.getCanonicalText(false); final String blockText; if (toBuilderAppendStatements.isEmpty()) { blockText = toBuilderPrependStatements + String.format("\nreturn new %s()%s;", canonicalText, toBuilderMethodCalls); } else { blockText = toBuilderPrependStatements + String.format("\nfinal %s %s = new %s()%s;\n", canonicalText, BUILDER_TEMP_VAR, canonicalText, toBuilderMethodCalls) + toBuilderAppendStatements + String.format("\nreturn %s;", BUILDER_TEMP_VAR); } methodBuilder.withBodyText(blockText); createRelevantNonNullAnnotation(containingClass, methodBuilder); return Optional.of(methodBuilder); }