Skip to content

Commit 9a2ae7c

Browse files
committed
fix(model-api-gen): generate separate default child setter for modelql
1 parent 1be20c2 commit 9a2ae7c

File tree

1 file changed

+64
-15
lines changed

1 file changed

+64
-15
lines changed

model-api-gen/src/main/kotlin/org/modelix/metamodel/generator/internal/ModelQLExtensionsGenerator.kt

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ internal class ModelQLExtensionsGenerator(
6767
is ProcessedChildLink -> {
6868
addChildGetter(feature)
6969
addChildSetter(feature)
70+
if (!feature.type.resolved.abstract) {
71+
addDefaultChildSetter(feature)
72+
}
7073
}
7174

7275
is ProcessedReferenceLink -> {
@@ -81,7 +84,7 @@ internal class ModelQLExtensionsGenerator(
8184

8285
private fun FileSpec.Builder.addReferenceSetter(referenceLink: ProcessedReferenceLink) {
8386
val targetType = referenceLink.type.resolved.nodeWrapperInterfaceType().copy(nullable = referenceLink.optional)
84-
val inputStepType = IMonoStep::class.asTypeName().parameterizedBy(concept.nodeWrapperInterfaceType())
87+
val inputStepType = getSetterReceiverType()
8588

8689
val parameterType = IMonoStep::class.asTypeName().parameterizedBy(targetType)
8790
.let { if (referenceLink.optional) it.copy(nullable = true) else it }
@@ -162,26 +165,21 @@ internal class ModelQLExtensionsGenerator(
162165
val targetType = childLink.type.resolved.nodeWrapperInterfaceType()
163166
val outType = TypeVariableName("Out", targetType)
164167
val returnType = IMonoStep::class.asTypeName().parameterizedBy(outType)
165-
val receiverType = IMonoStep::class.asTypeName().parameterizedBy(concept.nodeWrapperInterfaceType())
166-
val conceptParameter = ParameterSpec.builder("concept", IConceptOfTypedNode::class.asTypeName().parameterizedBy(outType)).apply {
167-
if (!childLink.type.resolved.abstract) {
168-
defaultValue("%T", childLink.type.resolved.conceptWrapperInterfaceClass())
169-
}
170-
}.build()
168+
val receiverType = getSetterReceiverType()
169+
val conceptParameter = ParameterSpec.builder(
170+
name = "concept",
171+
type = IConceptOfTypedNode::class.asTypeName().parameterizedBy(outType),
172+
).build()
171173

172-
val funName = if (childLink.multiple) childLink.adderMethodName() else childLink.setterName()
174+
val funName = getSetterName(childLink)
173175

174176
val funSpec = FunSpec.builder(funName).runBuild {
175177
addTypeVariable(outType)
176178
returns(returnType)
177179
receiver(receiverType)
178180
addParameter(conceptParameter)
179181
if (childLink.multiple) {
180-
val indexParameter = ParameterSpec.builder("index", Int::class.asTypeName())
181-
.defaultValue("-1")
182-
.build()
183-
184-
addParameter(indexParameter)
182+
addIndexParameter()
185183
addStatement(
186184
"return %T.addNewChild(this, %T.%N, index, concept)",
187185
TypedModelQL::class.asTypeName(),
@@ -201,6 +199,55 @@ internal class ModelQLExtensionsGenerator(
201199
addFunction(funSpec)
202200
}
203201

202+
/*
203+
If we use the concept companion object as a default value for the concept parameter,
204+
the kotlin compiler reports a type mismatch since it cannot properly infer the type variable.
205+
That's why we need a separate default setter.
206+
*/
207+
private fun FileSpec.Builder.addDefaultChildSetter(childLink: ProcessedChildLink) {
208+
val targetType = childLink.type.resolved.conceptWrapperInterfaceClass()
209+
val returnType = IMonoStep::class.asTypeName().parameterizedBy(childLink.type.resolved.nodeWrapperInterfaceType())
210+
val receiverType = getSetterReceiverType()
211+
212+
val funName = getSetterName(childLink)
213+
214+
val funSpec = FunSpec.builder(funName).runBuild {
215+
returns(returnType)
216+
receiver(receiverType)
217+
if (childLink.multiple) {
218+
addIndexParameter()
219+
addStatement(
220+
"return %T.addNewChild(this, %T.%N, index, %T)",
221+
TypedModelQL::class.asTypeName(),
222+
concept.conceptObjectType(),
223+
childLink.generatedName,
224+
targetType,
225+
)
226+
} else {
227+
addStatement(
228+
"return %T.setChild(this, %T.%N, %T)",
229+
TypedModelQL::class.asTypeName(),
230+
concept.conceptObjectType(),
231+
childLink.generatedName,
232+
targetType,
233+
)
234+
}
235+
}
236+
237+
addFunction(funSpec)
238+
}
239+
240+
private fun FunSpec.Builder.addIndexParameter() {
241+
val indexParameter = ParameterSpec.builder("index", Int::class.asTypeName())
242+
.defaultValue("-1")
243+
.build()
244+
245+
addParameter(indexParameter)
246+
}
247+
248+
private fun getSetterName(childLink: ProcessedChildLink) =
249+
if (childLink.multiple) childLink.adderMethodName() else childLink.setterName()
250+
204251
private fun FileSpec.Builder.addChildGetter(childLink: ProcessedChildLink) {
205252
val inputStepType = (if (childLink.multiple) IProducingStep::class else IMonoStep::class).asTypeName()
206253
val outputStepType = (if (childLink.multiple) IFluxStep::class else IMonoStep::class).asTypeName()
@@ -228,8 +275,7 @@ internal class ModelQLExtensionsGenerator(
228275
}
229276

230277
private fun FileSpec.Builder.addPropertySetter(property: ProcessedProperty) {
231-
val inputStepType = IMonoStep::class.asTypeName()
232-
.parameterizedBy(concept.nodeWrapperInterfaceType())
278+
val inputStepType = getSetterReceiverType()
233279

234280
val parameterType = IMonoStep::class.asTypeName()
235281
.parameterizedBy(property.asKotlinType(alwaysUseNonNullableProperties))
@@ -249,6 +295,9 @@ internal class ModelQLExtensionsGenerator(
249295
addFunction(setterSpec)
250296
}
251297

298+
private fun getSetterReceiverType() =
299+
IMonoStep::class.asTypeName().parameterizedBy(concept.nodeWrapperInterfaceType())
300+
252301
private fun FileSpec.Builder.addPropertyGetterForStepType(
253302
property: ProcessedProperty,
254303
stepType: ClassName,

0 commit comments

Comments
 (0)