PsiClass (@NotNull PsiClass psiClass, @NotNull PsiAnnotation psiAnnotation) { String builderClassName = getBuilderClassName(psiClass); String builderClassQualifiedName = psiClass.getQualifiedName() + "." + builderClassName; final LombokLightClassBuilder baseClassBuilder = new LombokLightClassBuilder(psiClass, builderClassName, builderClassQualifiedName) .withContainingClass(psiClass) .withNavigationElement(psiAnnotation) .withParameterTypes(psiClass.getTypeParameterList()) .withModifier(PsiModifier.PUBLIC) .withModifier(PsiModifier.STATIC) .withModifier(PsiModifier.ABSTRACT); final List<String> typeParamNames = ContainerUtil.map(psiClass.getTypeParameters(), PsiTypeParameter::getName); final LightTypeParameterBuilder c = new LightTypeParameterBuilder(selectNonClashingNameFor("C", typeParamNames), baseClassBuilder, 0); c.getExtendsList().addReference(PsiClassUtil.getTypeWithGenerics(psiClass)); baseClassBuilder.withParameterType(c); final LightTypeParameterBuilder b = new LightTypeParameterBuilder(selectNonClashingNameFor("B", typeParamNames), baseClassBuilder, 1); baseClassBuilder.withParameterType(b); b.getExtendsList().addReference(PsiClassUtil.getTypeWithGenerics(baseClassBuilder)); final PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); final PsiClassType bType = factory.createType(b); final PsiClassType cType = factory.createType(c); final PsiClass superClass = psiClass.getSuperClass(); if (null != superClass && !"Object".equals(superClass.getName())) { final PsiClass parentBuilderClass = superClass.findInnerClassByName(getBuilderClassName(superClass), false); if (null != parentBuilderClass) { final PsiType[] explicitTypes = Stream.concat( Stream.of(psiClass.getExtendsListTypes()).map(PsiClassType::getParameters).flatMap(Stream::of), Stream.of(cType, bType)) .toArray(PsiType[]::new); final PsiClassType extendsType = getTypeWithSpecificTypeParameters(parentBuilderClass, explicitTypes); baseClassBuilder.withExtends(extendsType); } } baseClassBuilder.withFieldSupplier((thisPsiClass) -> { final List<BuilderInfo> builderInfos = createBuilderInfos(psiClass, psiAnnotation, thisPsiClass); initBuilderInfosBuilderClassType(builderInfos, bType); // create builder Fields return builderInfos.stream() .map(BuilderInfo::renderBuilderFields) .flatMap(Collection::stream) .collect(Collectors.toList()); }); baseClassBuilder.withMethodSupplier((thisPsiClass) -> { final List<BuilderInfo> builderInfos = createBuilderInfos(psiClass, psiAnnotation, thisPsiClass); initBuilderInfosBuilderClassType(builderInfos, bType); // create all methods return addAllMethodsForBaseBuilderClass(psiClass, psiAnnotation, thisPsiClass, builderInfos, bType, cType); }); return baseClassBuilder; }