@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
14
14
import org.jetbrains.kotlin.ir.declarations.IrField
15
15
import org.jetbrains.kotlin.ir.declarations.IrFile
16
16
import org.jetbrains.kotlin.ir.declarations.IrFunction
17
+ import org.jetbrains.kotlin.ir.declarations.IrParameterKind
17
18
import org.jetbrains.kotlin.ir.declarations.path
18
19
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
19
20
import org.jetbrains.kotlin.ir.expressions.IrBody
@@ -23,7 +24,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
23
24
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
24
25
import org.jetbrains.kotlin.ir.expressions.IrGetValue
25
26
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
26
- import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
27
+ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImplWithShape
27
28
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
28
29
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl
29
30
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
@@ -38,8 +39,8 @@ import org.jetbrains.kotlin.ir.types.typeWith
38
39
import org.jetbrains.kotlin.ir.util.SetDeclarationsParentVisitor
39
40
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
40
41
import org.jetbrains.kotlin.ir.util.isLocal
41
- import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
42
42
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
43
+ import org.jetbrains.kotlin.ir.visitors.IrTransformer
43
44
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
44
45
import org.jetbrains.kotlin.name.CallableId
45
46
import org.jetbrains.kotlin.name.ClassId
@@ -51,8 +52,8 @@ data class ContainingDeclarations(val clazz: IrClass?, val function: IrFunction?
51
52
52
53
@OptIn(UnsafeDuringIrConstructionAPI ::class )
53
54
class ExplainerIrTransformer (val pluginContext : IrPluginContext ) :
54
- FileLoweringPass ,
55
- IrElementTransformer < ContainingDeclarations > {
55
+ IrTransformer < ContainingDeclarations >() ,
56
+ FileLoweringPass {
56
57
lateinit var file: IrFile
57
58
lateinit var source: String
58
59
@@ -151,12 +152,15 @@ class ExplainerIrTransformer(val pluginContext: IrPluginContext) :
151
152
if (expression.startOffset < 0 ) return expression
152
153
if (expression.type.classFqName in dataFrameLike) {
153
154
if (expression.symbol.owner.name == Name .identifier(" component1" )) return expression
154
- var receiver = expression.extensionReceiver
155
- // expression.extensionReceiver = extension callables,
155
+ val extensionReceiverIndex =
156
+ expression.symbol.owner.parameters.indexOfFirst { it.kind == IrParameterKind .ExtensionReceiver }
157
+ var receiver: IrExpression ?
158
+ // expression.arguments[extensionReceiverIndex] = extension callables,
156
159
// expression.dispatchReceiver = member callables such as "GroupBy.aggregate"
157
- if (receiver != null ) {
158
- val transformedExtensionReceiver = expression.extensionReceiver?.transform(this , data)
159
- expression.extensionReceiver = transformedExtensionReceiver
160
+ if (extensionReceiverIndex >= 0 ) {
161
+ receiver = expression.arguments[extensionReceiverIndex]!!
162
+ val transformedExtensionReceiver = receiver.transform(this , data)
163
+ expression.arguments[extensionReceiverIndex] = transformedExtensionReceiver
160
164
} else {
161
165
receiver = expression.dispatchReceiver
162
166
val transformedExtensionReceiver = expression.dispatchReceiver?.transform(this , data)
@@ -179,9 +183,26 @@ class ExplainerIrTransformer(val pluginContext: IrPluginContext) :
179
183
CallableId (FqName (" kotlin" ), Name .identifier(" also" )),
180
184
).single()
181
185
182
- val result = IrCallImpl (- 1 , - 1 , expression.type, alsoReference, 1 , 1 ).apply {
183
- this .extensionReceiver = expression
184
- putTypeArgument(0 , expression.type)
186
+ val result = IrCallImplWithShape (
187
+ startOffset = - 1 ,
188
+ endOffset = - 1 ,
189
+ type = expression.type,
190
+ symbol = alsoReference,
191
+ typeArgumentsCount = 1 ,
192
+ valueArgumentsCount = 1 ,
193
+ contextParameterCount = 0 ,
194
+ hasDispatchReceiver = true ,
195
+ hasExtensionReceiver = true ,
196
+ ).apply {
197
+ val extensionReceiverIndex =
198
+ this .symbol.owner.parameters.indexOfFirst { it.kind == IrParameterKind .ExtensionReceiver }
199
+ if (extensionReceiverIndex >= 0 ) {
200
+ this .arguments[extensionReceiverIndex] = expression
201
+ } else {
202
+ this .insertExtensionReceiver(expression)
203
+ }
204
+
205
+ typeArguments[0 ] = expression.type
185
206
186
207
val symbol = IrSimpleFunctionSymbolImpl ()
187
208
val alsoLambda = pluginContext.irFactory
@@ -202,25 +223,24 @@ class ExplainerIrTransformer(val pluginContext: IrPluginContext) :
202
223
isInfix = false ,
203
224
isExpect = false ,
204
225
).apply {
205
- valueParameters = buildList {
206
- add(
207
- pluginContext.irFactory.createValueParameter(
208
- startOffset = - 1 ,
209
- endOffset = - 1 ,
210
- origin = IrDeclarationOrigin .DEFINED ,
211
- symbol = IrValueParameterSymbolImpl (),
212
- name = Name .identifier(" it" ),
213
- index = 0 ,
214
- type = expression.type,
215
- varargElementType = null ,
216
- isCrossinline = false ,
217
- isNoinline = false ,
218
- isHidden = false ,
219
- isAssignable = false ,
220
- ),
226
+ // replace all regular value parameters with a single one `it`
227
+ parameters = parameters.filterNot { it.kind == IrParameterKind .Regular } +
228
+ pluginContext.irFactory.createValueParameter(
229
+ startOffset = - 1 ,
230
+ endOffset = - 1 ,
231
+ origin = IrDeclarationOrigin .DEFINED ,
232
+ kind = IrParameterKind .Regular ,
233
+ name = Name .identifier(" it" ),
234
+ type = expression.type,
235
+ isAssignable = false ,
236
+ symbol = IrValueParameterSymbolImpl (),
237
+ varargElementType = null ,
238
+ isCrossinline = false ,
239
+ isNoinline = false ,
240
+ isHidden = false ,
221
241
)
222
- }
223
- val itSymbol = valueParameters[ 0 ] .symbol
242
+
243
+ val itSymbol = parameters.first { it.kind == IrParameterKind . Regular } .symbol
224
244
val source = try {
225
245
source.substring(expression.startOffset, expression.endOffset)
226
246
} catch (e: Exception ) {
@@ -229,14 +249,21 @@ class ExplainerIrTransformer(val pluginContext: IrPluginContext) :
229
249
val expressionId = expressionId(expression)
230
250
val receiverId = receiver?.let { expressionId(it) }
231
251
val valueArguments = buildList<IrExpression ?> {
232
- add(source.irConstImpl())
233
- add(ownerName.asStringStripSpecialMarkers().irConstImpl())
234
- add(IrGetValueImpl (- 1 , - 1 , itSymbol))
235
- add(expressionId.irConstImpl())
236
- add(receiverId.irConstImpl())
237
- add(data.clazz?.fqNameWhenAvailable?.asString().irConstImpl())
238
- add(data.function?.name?.asString().irConstImpl())
239
- add(IrConstImpl .int(- 1 , - 1 , pluginContext.irBuiltIns.intType, data.statementIndex))
252
+ add(source.irConstImpl()) // source: String
253
+ add(ownerName.asStringStripSpecialMarkers().irConstImpl()) // name: String
254
+ add(IrGetValueImpl (- 1 , - 1 , itSymbol)) // df: Any
255
+ add(expressionId.irConstImpl()) // id: String
256
+ add(receiverId.irConstImpl()) // receiverId: String?
257
+ add(data.clazz?.fqNameWhenAvailable?.asString().irConstImpl()) // containingClassFqName: String?
258
+ add(data.function?.name?.asString().irConstImpl()) // containingFunName: String?
259
+ add(
260
+ IrConstImpl .int(
261
+ - 1 ,
262
+ - 1 ,
263
+ pluginContext.irBuiltIns.intType,
264
+ data.statementIndex,
265
+ ),
266
+ ) // statementIndex: Int
240
267
}
241
268
body = pluginContext.irFactory.createBlockBody(- 1 , - 1 ).apply {
242
269
val callableId = CallableId (
@@ -245,19 +272,24 @@ class ExplainerIrTransformer(val pluginContext: IrPluginContext) :
245
272
Name .identifier(" doAction" ),
246
273
)
247
274
val doAction = pluginContext.referenceFunctions(callableId).single()
248
- statements + = IrCallImpl (
275
+ statements + = IrCallImplWithShape (
249
276
startOffset = - 1 ,
250
277
endOffset = - 1 ,
251
278
type = doAction.owner.returnType,
252
279
symbol = doAction,
253
280
typeArgumentsCount = 0 ,
254
281
valueArgumentsCount = valueArguments.size,
282
+ contextParameterCount = 0 ,
283
+ hasDispatchReceiver = true ,
284
+ hasExtensionReceiver = false ,
255
285
).apply {
256
286
val clazz = ClassId (explainerPackage, Name .identifier(" PluginCallbackProxy" ))
257
287
val plugin = pluginContext.referenceClass(clazz)!!
258
288
dispatchReceiver = IrGetObjectValueImpl (- 1 , - 1 , plugin.defaultType, plugin)
289
+
290
+ val firstValueArgumentIndex = 1 // skipping dispatch receiver
259
291
valueArguments.forEachIndexed { i, argument ->
260
- putValueArgument(i, argument)
292
+ this .arguments[firstValueArgumentIndex + i] = argument
261
293
}
262
294
}
263
295
}
@@ -271,12 +303,16 @@ class ExplainerIrTransformer(val pluginContext: IrPluginContext) :
271
303
function = alsoLambda,
272
304
origin = IrStatementOrigin .LAMBDA ,
273
305
)
274
- putValueArgument(0 , alsoLambdaExpression)
306
+
307
+ val firstValueArgumentIndex = this .symbol.owner.parameters
308
+ .indexOfFirst { it.kind == IrParameterKind .Regular }
309
+ .takeUnless { it < 0 } ? : this .symbol.owner.parameters.size
310
+ this .arguments[firstValueArgumentIndex] = alsoLambdaExpression
275
311
}
276
312
return result
277
313
}
278
314
279
- private fun String?.irConstImpl (): IrConstImpl < out String ?> {
315
+ private fun String?.irConstImpl (): IrConstImpl {
280
316
val nullableString = pluginContext.irBuiltIns.stringType.makeNullable()
281
317
val argument = if (this == null ) {
282
318
IrConstImpl .constNull(- 1 , - 1 , nullableString)
0 commit comments