@@ -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