-
Notifications
You must be signed in to change notification settings - Fork 645
/
BuilderBuilder.kt
96 lines (88 loc) · 3.32 KB
/
BuilderBuilder.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.apollographql.apollo3.compiler.codegen.java.helpers
import com.apollographql.apollo3.compiler.applyIf
import com.apollographql.apollo3.compiler.codegen.java.JavaClassNames
import com.apollographql.apollo3.compiler.codegen.java.JavaContext
import com.apollographql.apollo3.compiler.codegen.java.L
import com.apollographql.apollo3.compiler.codegen.java.T
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.CodeBlock
import com.squareup.javapoet.FieldSpec
import com.squareup.javapoet.MethodSpec
import com.squareup.javapoet.ParameterSpec
import com.squareup.javapoet.TypeSpec
import javax.lang.model.element.Modifier
internal class BuilderBuilder(
val targetObjectClassName: ClassName,
val fields: List<FieldSpec>,
val context: JavaContext,
) {
fun build(): TypeSpec {
return TypeSpec.classBuilder(JavaClassNames.Builder.simpleName())
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.addFields(builderFields())
.addMethod(MethodSpec.constructorBuilder().build())
.addMethods(fieldSetterMethodSpecs())
.addMethod(buildMethod())
.build()
}
private fun builderFields(): List<FieldSpec> {
return fields.map {
FieldSpec.builder(it.type, it.name, Modifier.PRIVATE)
.applyIf(context.resolver.isOptional(it.type)) {
initializer(context.absentOptionalInitializer())
}
.build()
}
}
private fun fieldSetterMethodSpecs(): List<MethodSpec> {
return fields.map {
fieldSetterMethodSpec(it)
}
}
private fun fieldSetterMethodSpec(field: FieldSpec): MethodSpec {
val unwrappedFieldType = context.resolver.unwrapFromOptional(field.type)
return MethodSpec.methodBuilder(field.name)
.addModifiers(Modifier.PUBLIC)
.addParameter(
ParameterSpec.builder(unwrappedFieldType, field.name)
.apply {
if (context.resolver.isOptional(unwrappedFieldType)) {
addAnnotation(context.resolver.notNullAnnotationClassName ?: JavaClassNames.JetBrainsNonNull)
} else if (!context.resolver.isOptional(field.type)) {
addAnnotations(field.annotations)
}
}
.build()
)
.applyIf(!field.javadoc.isEmpty) {
addJavadoc(L, field.javadoc)
}
.returns(JavaClassNames.Builder)
.addStatement("this.$L = $L", field.name, context.wrapValueInOptional(value = CodeBlock.of(L, field.name), fieldType = field.type))
.addStatement("return this")
.build()
}
private fun buildMethod(): MethodSpec {
return MethodSpec
.methodBuilder("build")
.addModifiers(Modifier.PUBLIC)
.returns(targetObjectClassName)
.addStatement(
"return new $T$L",
targetObjectClassName,
fields.joinToString(prefix = "(", separator = ", ", postfix = ")") { it.name }
)
.build()
}
companion object {
const val TO_BUILDER_METHOD_NAME = "toBuilder"
fun builderFactoryMethod(): MethodSpec {
return MethodSpec
.methodBuilder("builder")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(JavaClassNames.Builder)
.addStatement("return new $T()", JavaClassNames.Builder)
.build()
}
}
}