Skip to content

Commit 841340b

Browse files
committed
Kotlin: Resugar for loops
1 parent 1e30605 commit 841340b

File tree

7 files changed

+159
-122
lines changed

7 files changed

+159
-122
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 115 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,7 @@ open class KotlinFileExtractor(
14991499
}
15001500
}
15011501

1502-
private fun extractVariableExpr(v: IrVariable, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int, enclosingStmt: Label<out DbStmt>) {
1502+
private fun extractVariableExpr(v: IrVariable, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int, enclosingStmt: Label<out DbStmt>, extractInitializer: Boolean = true) {
15031503
with("variable expr", v) {
15041504
val varId = useVariable(v)
15051505
val exprId = tw.getFreshIdLabel<DbLocalvariabledeclexpr>()
@@ -1514,7 +1514,7 @@ open class KotlinFileExtractor(
15141514
tw.writeCallableEnclosingExpr(exprId, callable)
15151515
tw.writeStatementEnclosingExpr(exprId, enclosingStmt)
15161516
val i = v.initializer
1517-
if (i != null) {
1517+
if (i != null && extractInitializer) {
15181518
extractExpressionExpr(i, callable, exprId, 0, enclosingStmt)
15191519
}
15201520
if (!v.isVar) {
@@ -3174,6 +3174,85 @@ open class KotlinFileExtractor(
31743174
}
31753175
}
31763176

3177+
/**
3178+
* This method tries to extract a block as an enhanced for loop.
3179+
* It returns true if it succeeds, and false otherwise.
3180+
*/
3181+
private fun tryExtractForLoop(e: IrContainerExpression, callable: Label<out DbCallable>, parent: StmtExprParent): Boolean {
3182+
/*
3183+
* We're expecting the pattern
3184+
* {
3185+
* val iterator = [expr].iterator()
3186+
* while (iterator.hasNext()) {
3187+
* val [loopVar] = iterator.next()
3188+
* [block]
3189+
* }
3190+
* }
3191+
*/
3192+
3193+
if (e.origin != IrStatementOrigin.FOR_LOOP ||
3194+
e.statements.size != 2 ||
3195+
(e.statements[0] as? IrVariable)?.origin != IrDeclarationOrigin.FOR_LOOP_ITERATOR ||
3196+
(e.statements[1] as? IrWhileLoop)?.origin != IrStatementOrigin.FOR_LOOP_INNER_WHILE) {
3197+
return false
3198+
}
3199+
3200+
val iteratorVariable = e.statements[0] as? IrVariable
3201+
val innerWhile = e.statements[1] as? IrWhileLoop
3202+
3203+
if (iteratorVariable == null ||
3204+
iteratorVariable.origin != IrDeclarationOrigin.FOR_LOOP_ITERATOR ||
3205+
innerWhile == null ||
3206+
innerWhile.origin != IrStatementOrigin.FOR_LOOP_INNER_WHILE) {
3207+
return false
3208+
}
3209+
3210+
val initializer = iteratorVariable.initializer as? IrCall
3211+
if (initializer == null ||
3212+
initializer.origin != IrStatementOrigin.FOR_LOOP_ITERATOR ||
3213+
initializer.symbol.owner.name.asString() != "iterator") {
3214+
return false
3215+
}
3216+
3217+
val expr = initializer.dispatchReceiver
3218+
val cond = innerWhile.condition as? IrCall
3219+
val body = innerWhile.body as? IrBlock
3220+
3221+
if (expr == null ||
3222+
cond == null ||
3223+
cond.origin != IrStatementOrigin.FOR_LOOP_HAS_NEXT ||
3224+
(cond.dispatchReceiver as? IrGetValue)?.symbol?.owner != iteratorVariable ||
3225+
body == null ||
3226+
body.origin != IrStatementOrigin.FOR_LOOP_INNER_WHILE ||
3227+
body.statements.size != 2) {
3228+
return false
3229+
}
3230+
3231+
val loopVar = body.statements[0] as? IrVariable
3232+
val block = body.statements[1] as? IrBlock
3233+
val nextCall = loopVar?.initializer as? IrCall
3234+
3235+
if (loopVar == null ||
3236+
!(loopVar.origin == IrDeclarationOrigin.FOR_LOOP_VARIABLE || loopVar.origin == IrDeclarationOrigin.IR_TEMPORARY_VARIABLE) ||
3237+
nextCall == null ||
3238+
nextCall.origin != IrStatementOrigin.FOR_LOOP_NEXT ||
3239+
(nextCall.dispatchReceiver as? IrGetValue)?.symbol?.owner != iteratorVariable) {
3240+
return false
3241+
}
3242+
3243+
val id = extractLoop(innerWhile, block, 2, parent, callable) { p, idx ->
3244+
val loopId = tw.getFreshIdLabel<DbEnhancedforstmt>()
3245+
tw.writeStmts_enhancedforstmt(loopId, p, idx, callable)
3246+
loopId
3247+
}
3248+
3249+
extractExpressionExpr(expr, callable, id, 1, id)
3250+
extractVariableExpr(loopVar, callable, id, 0, id, extractInitializer = false)
3251+
3252+
return true
3253+
}
3254+
3255+
31773256
/**
31783257
* This tried to extract a block as an array update.
31793258
* It returns true if it succeeds, and false otherwise.
@@ -3405,7 +3484,9 @@ open class KotlinFileExtractor(
34053484
}
34063485
}
34073486
is IrContainerExpression -> {
3408-
if(!tryExtractArrayUpdate(e, callable, parent)) {
3487+
if (!tryExtractArrayUpdate(e, callable, parent) &&
3488+
!tryExtractForLoop(e, callable, parent)) {
3489+
34093490
val stmtParent = parent.stmt(e, callable)
34103491
val id = tw.getFreshIdLabel<DbBlock>()
34113492
val locId = tw.getLocation(e)
@@ -3417,10 +3498,10 @@ open class KotlinFileExtractor(
34173498
}
34183499
}
34193500
is IrWhileLoop -> {
3420-
extractLoop(e, parent, callable)
3501+
extractLoopWithCondition(e, parent, callable)
34213502
}
34223503
is IrDoWhileLoop -> {
3423-
extractLoop(e, parent, callable)
3504+
extractLoopWithCondition(e, parent, callable)
34243505
}
34253506
is IrInstanceInitializerCall -> {
34263507
val irConstructor = declarationStack.peek().first as? IrConstructor
@@ -3993,9 +4074,12 @@ open class KotlinFileExtractor(
39934074

39944075
private fun extractLoop(
39954076
loop: IrLoop,
4077+
body: IrExpression?,
4078+
bodyIdx: Int,
39964079
stmtExprParent: StmtExprParent,
3997-
callable: Label<out DbCallable>
3998-
) {
4080+
callable: Label<out DbCallable>,
4081+
getId: (Label<out DbStmtparent>, Int) -> Label<out DbStmt>
4082+
) : Label<out DbStmt> {
39994083
val stmtParent = stmtExprParent.stmt(loop, callable)
40004084
val locId = tw.getLocation(loop)
40014085

@@ -4016,22 +4100,33 @@ open class KotlinFileExtractor(
40164100
parent = stmtParent.parent
40174101
}
40184102

4019-
val id = if (loop is IrWhileLoop) {
4020-
val id = tw.getFreshIdLabel<DbWhilestmt>()
4021-
tw.writeStmts_whilestmt(id, parent, idx, callable)
4022-
id
4023-
} else {
4024-
val id = tw.getFreshIdLabel<DbDostmt>()
4025-
tw.writeStmts_dostmt(id, parent, idx, callable)
4026-
id
4027-
}
4028-
4103+
val id = getId(parent, idx)
40294104
tw.writeHasLocation(id, locId)
4030-
extractExpressionExpr(loop.condition, callable, id, 0, id)
4031-
val body = loop.body
4105+
40324106
if (body != null) {
4033-
extractExpressionStmt(body, callable, id, 1)
4107+
extractExpressionStmt(body, callable, id, bodyIdx)
4108+
}
4109+
4110+
return id
4111+
}
4112+
4113+
private fun extractLoopWithCondition(
4114+
loop: IrLoop,
4115+
stmtExprParent: StmtExprParent,
4116+
callable: Label<out DbCallable>
4117+
) {
4118+
val id = extractLoop(loop, loop.body, 1, stmtExprParent, callable) { parent, idx ->
4119+
if (loop is IrWhileLoop) {
4120+
val id = tw.getFreshIdLabel<DbWhilestmt>()
4121+
tw.writeStmts_whilestmt(id, parent, idx, callable)
4122+
id
4123+
} else {
4124+
val id = tw.getFreshIdLabel<DbDostmt>()
4125+
tw.writeStmts_dostmt(id, parent, idx, callable)
4126+
id
4127+
}
40344128
}
4129+
extractExpressionExpr(loop.condition, callable, id, 0, id)
40354130
}
40364131

40374132
private fun IrValueParameter.isExtensionReceiver(): Boolean {
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
| arrayIterators.kt:6:15:6:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt |
2-
| arrayIterators.kt:7:15:7:15 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt |
3-
| arrayIterators.kt:8:15:8:15 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt |
41
| arrayIterators.kt:10:16:10:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt |
52
| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt |
63
| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt |
Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +0,0 @@
1-
| test.kt:5:14:5:14 | hasNext(...) |
2-
| test.kt:5:14:5:14 | iterator(...) |
3-
| test.kt:5:14:5:14 | next(...) |
4-
| test.kt:6:14:6:14 | hasNext(...) |
5-
| test.kt:6:14:6:14 | iterator(...) |
6-
| test.kt:6:14:6:14 | next(...) |
7-
| test.kt:7:14:7:14 | hasNext(...) |
8-
| test.kt:7:14:7:14 | iterator(...) |
9-
| test.kt:7:14:7:14 | next(...) |

java/ql/test/kotlin/library-tests/stmts/PrintAst.expected

Lines changed: 35 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -116,59 +116,41 @@ stmts.kt:
116116
# 28| 0: [VarAccess] x
117117
# 28| 1: [VarAccess] y
118118
# 29| 1: [ContinueStmt] continue
119-
# 31| 2: [BlockStmt] { ... }
120-
# 31| 0: [LocalVariableDeclStmt] var ...;
121-
# 31| 1: [LocalVariableDeclExpr] tmp0_iterator
122-
# 31| 0: [MethodAccess] iterator(...)
123-
# 31| -1: [MethodAccess] rangeTo(...)
124-
# 31| -1: [VarAccess] x
125-
# 31| 0: [VarAccess] y
126-
# 31| 1: [WhileStmt] while (...)
127-
# 31| 0: [MethodAccess] hasNext(...)
128-
# 31| -1: [VarAccess] tmp0_iterator
129-
# 31| 1: [BlockStmt] { ... }
130-
# 31| 0: [LocalVariableDeclStmt] var ...;
131-
# 31| 1: [LocalVariableDeclExpr] i
132-
# 31| 0: [MethodAccess] next(...)
133-
# 31| -1: [VarAccess] tmp0_iterator
134-
# 31| 1: [BlockStmt] { ... }
135-
# 32| 0: [ExprStmt] <Expr>;
136-
# 32| 0: [WhenExpr] when ...
137-
# 32| 0: [WhenBranch] ... -> ...
138-
# 32| 0: [GTExpr] ... > ...
139-
# 32| 0: [VarAccess] x
140-
# 32| 1: [VarAccess] y
141-
# 32| 1: [BreakStmt] break
142-
# 35| 3: [BlockStmt] { ... }
143-
# 35| 0: [LocalVariableDeclStmt] var ...;
144-
# 35| 1: [LocalVariableDeclExpr] tmp1_iterator
145-
# 35| 0: [MethodAccess] iterator(...)
146-
# 35| -1: [MethodAccess] rangeTo(...)
147-
# 35| -1: [VarAccess] x
148-
# 35| 0: [VarAccess] y
149-
# 35| 1: [LabeledStmt] <Label>: ...
150-
# 35| 0: [WhileStmt] while (...)
151-
# 35| 0: [MethodAccess] hasNext(...)
152-
# 35| -1: [VarAccess] tmp1_iterator
153-
# 35| 1: [BlockStmt] { ... }
154-
# 35| 0: [LocalVariableDeclStmt] var ...;
155-
# 35| 1: [LocalVariableDeclExpr] i
156-
# 35| 0: [MethodAccess] next(...)
157-
# 35| -1: [VarAccess] tmp1_iterator
158-
# 35| 1: [BlockStmt] { ... }
159-
# 36| 0: [BlockStmt] { ... }
160-
# 36| 0: [DoStmt] do ... while (...)
161-
# 38| 0: [GTExpr] ... > ...
162-
# 38| 0: [VarAccess] y
163-
# 38| 1: [IntegerLiteral] 100
164-
# 36| 1: [BlockStmt] { ... }
165-
# 37| 0: [ExprStmt] <Expr>;
166-
# 37| 0: [WhenExpr] when ...
167-
# 37| 0: [WhenBranch] ... -> ...
168-
# 37| 0: [GTExpr] ... > ...
169-
# 37| 0: [VarAccess] x
170-
# 37| 1: [VarAccess] y
171-
# 37| 1: [BreakStmt] break
119+
# 31| 2: [EnhancedForStmt] for (... : ...)
120+
#-----| 0: (Single Local Variable Declaration)
121+
# 31| 1: [LocalVariableDeclExpr] i
122+
# 31| 1: [MethodAccess] rangeTo(...)
123+
# 31| -1: [VarAccess] x
124+
# 31| 0: [VarAccess] y
125+
# 31| 2: [BlockStmt] { ... }
126+
# 32| 0: [ExprStmt] <Expr>;
127+
# 32| 0: [WhenExpr] when ...
128+
# 32| 0: [WhenBranch] ... -> ...
129+
# 32| 0: [GTExpr] ... > ...
130+
# 32| 0: [VarAccess] x
131+
# 32| 1: [VarAccess] y
132+
# 32| 1: [BreakStmt] break
133+
# 35| 3: [LabeledStmt] <Label>: ...
134+
# 35| 0: [EnhancedForStmt] for (... : ...)
135+
#-----| 0: (Single Local Variable Declaration)
136+
# 35| 1: [LocalVariableDeclExpr] i
137+
# 35| 1: [MethodAccess] rangeTo(...)
138+
# 35| -1: [VarAccess] x
139+
# 35| 0: [VarAccess] y
140+
# 35| 2: [BlockStmt] { ... }
141+
# 36| 0: [BlockStmt] { ... }
142+
# 36| 0: [DoStmt] do ... while (...)
143+
# 38| 0: [GTExpr] ... > ...
144+
# 38| 0: [VarAccess] y
145+
# 38| 1: [IntegerLiteral] 100
146+
# 36| 1: [BlockStmt] { ... }
147+
# 37| 0: [ExprStmt] <Expr>;
148+
# 37| 0: [WhenExpr] when ...
149+
# 37| 0: [WhenBranch] ... -> ...
150+
# 37| 0: [GTExpr] ... > ...
151+
# 37| 0: [VarAccess] x
152+
# 37| 1: [VarAccess] y
153+
# 37| 1: [BreakStmt] break
172154
# 41| 4: [BlockStmt] { ... }
173155
# 41| 0: [LocalVariableDeclStmt] var ...;
174156
# 41| 1: [LocalVariableDeclExpr] tmp2_iterator

java/ql/test/kotlin/library-tests/stmts/exprs.expected

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -64,27 +64,15 @@
6464
| stmts.kt:28:15:28:15 | y | VarAccess |
6565
| stmts.kt:31:10:31:10 | i | LocalVariableDeclExpr |
6666
| stmts.kt:31:15:31:15 | x | VarAccess |
67-
| stmts.kt:31:15:31:18 | hasNext(...) | MethodAccess |
68-
| stmts.kt:31:15:31:18 | iterator(...) | MethodAccess |
69-
| stmts.kt:31:15:31:18 | next(...) | MethodAccess |
7067
| stmts.kt:31:15:31:18 | rangeTo(...) | MethodAccess |
71-
| stmts.kt:31:15:31:18 | tmp0_iterator | LocalVariableDeclExpr |
72-
| stmts.kt:31:15:31:18 | tmp0_iterator | VarAccess |
73-
| stmts.kt:31:15:31:18 | tmp0_iterator | VarAccess |
7468
| stmts.kt:31:18:31:18 | y | VarAccess |
7569
| stmts.kt:32:9:32:24 | when ... | WhenExpr |
7670
| stmts.kt:32:13:32:13 | x | VarAccess |
7771
| stmts.kt:32:13:32:17 | ... > ... | GTExpr |
7872
| stmts.kt:32:17:32:17 | y | VarAccess |
7973
| stmts.kt:35:18:35:18 | i | LocalVariableDeclExpr |
8074
| stmts.kt:35:23:35:23 | x | VarAccess |
81-
| stmts.kt:35:23:35:26 | hasNext(...) | MethodAccess |
82-
| stmts.kt:35:23:35:26 | iterator(...) | MethodAccess |
83-
| stmts.kt:35:23:35:26 | next(...) | MethodAccess |
8475
| stmts.kt:35:23:35:26 | rangeTo(...) | MethodAccess |
85-
| stmts.kt:35:23:35:26 | tmp1_iterator | LocalVariableDeclExpr |
86-
| stmts.kt:35:23:35:26 | tmp1_iterator | VarAccess |
87-
| stmts.kt:35:23:35:26 | tmp1_iterator | VarAccess |
8876
| stmts.kt:35:26:35:26 | y | VarAccess |
8977
| stmts.kt:37:13:37:36 | when ... | WhenExpr |
9078
| stmts.kt:37:17:37:17 | x | VarAccess |

java/ql/test/kotlin/library-tests/stmts/loops.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ continueLabel
55
jumpTarget
66
| stmts.kt:25:24:25:33 | break | stmts.kt:23:11:27:5 | while (...) |
77
| stmts.kt:29:9:29:16 | continue | stmts.kt:28:5:29:16 | while (...) |
8-
| stmts.kt:32:20:32:24 | break | stmts.kt:31:5:33:5 | while (...) |
9-
| stmts.kt:37:24:37:36 | break | stmts.kt:35:13:39:5 | while (...) |
8+
| stmts.kt:32:20:32:24 | break | stmts.kt:31:5:33:5 | for (... : ...) |
9+
| stmts.kt:37:24:37:36 | break | stmts.kt:35:13:39:5 | for (... : ...) |
1010
| stmts.kt:42:20:42:24 | break | stmts.kt:41:5:43:5 | while (...) |

java/ql/test/kotlin/library-tests/stmts/stmts.expected

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,14 @@ enclosing
4040
| stmts.kt:25:24:25:33 | break | stmts.kt:25:13:25:33 | ... -> ... |
4141
| stmts.kt:28:5:29:16 | while (...) | stmts.kt:22:27:44:1 | { ... } |
4242
| stmts.kt:29:9:29:16 | continue | stmts.kt:28:5:29:16 | while (...) |
43-
| stmts.kt:31:5:33:5 | while (...) | stmts.kt:31:5:33:5 | { ... } |
44-
| stmts.kt:31:5:33:5 | { ... } | stmts.kt:22:27:44:1 | { ... } |
45-
| stmts.kt:31:5:33:5 | { ... } | stmts.kt:31:5:33:5 | while (...) |
46-
| stmts.kt:31:10:31:10 | var ...; | stmts.kt:31:5:33:5 | { ... } |
47-
| stmts.kt:31:15:31:18 | var ...; | stmts.kt:31:5:33:5 | { ... } |
48-
| stmts.kt:31:21:33:5 | { ... } | stmts.kt:31:5:33:5 | { ... } |
43+
| stmts.kt:31:5:33:5 | for (... : ...) | stmts.kt:22:27:44:1 | { ... } |
44+
| stmts.kt:31:21:33:5 | { ... } | stmts.kt:31:5:33:5 | for (... : ...) |
4945
| stmts.kt:32:9:32:24 | ... -> ... | stmts.kt:32:9:32:24 | <Expr>; |
5046
| stmts.kt:32:9:32:24 | <Expr>; | stmts.kt:31:21:33:5 | { ... } |
5147
| stmts.kt:32:20:32:24 | break | stmts.kt:32:9:32:24 | ... -> ... |
52-
| stmts.kt:35:13:39:5 | <Label>: ... | stmts.kt:35:13:39:5 | { ... } |
53-
| stmts.kt:35:13:39:5 | while (...) | stmts.kt:35:13:39:5 | <Label>: ... |
54-
| stmts.kt:35:13:39:5 | { ... } | stmts.kt:22:27:44:1 | { ... } |
55-
| stmts.kt:35:13:39:5 | { ... } | stmts.kt:35:13:39:5 | while (...) |
56-
| stmts.kt:35:18:35:18 | var ...; | stmts.kt:35:13:39:5 | { ... } |
57-
| stmts.kt:35:23:35:26 | var ...; | stmts.kt:35:13:39:5 | { ... } |
58-
| stmts.kt:35:29:39:5 | { ... } | stmts.kt:35:13:39:5 | { ... } |
48+
| stmts.kt:35:13:39:5 | <Label>: ... | stmts.kt:22:27:44:1 | { ... } |
49+
| stmts.kt:35:13:39:5 | for (... : ...) | stmts.kt:35:13:39:5 | <Label>: ... |
50+
| stmts.kt:35:29:39:5 | { ... } | stmts.kt:35:13:39:5 | for (... : ...) |
5951
| stmts.kt:36:9:38:25 | do ... while (...) | stmts.kt:36:9:38:25 | { ... } |
6052
| stmts.kt:36:9:38:25 | { ... } | stmts.kt:35:29:39:5 | { ... } |
6153
| stmts.kt:36:13:38:9 | { ... } | stmts.kt:36:9:38:25 | do ... while (...) |
@@ -125,21 +117,13 @@ enclosing
125117
| stmts.kt:25:24:25:33 | break | BreakStmt |
126118
| stmts.kt:28:5:29:16 | while (...) | WhileStmt |
127119
| stmts.kt:29:9:29:16 | continue | ContinueStmt |
128-
| stmts.kt:31:5:33:5 | while (...) | WhileStmt |
129-
| stmts.kt:31:5:33:5 | { ... } | BlockStmt |
130-
| stmts.kt:31:5:33:5 | { ... } | BlockStmt |
131-
| stmts.kt:31:10:31:10 | var ...; | LocalVariableDeclStmt |
132-
| stmts.kt:31:15:31:18 | var ...; | LocalVariableDeclStmt |
120+
| stmts.kt:31:5:33:5 | for (... : ...) | EnhancedForStmt |
133121
| stmts.kt:31:21:33:5 | { ... } | BlockStmt |
134122
| stmts.kt:32:9:32:24 | ... -> ... | WhenBranch |
135123
| stmts.kt:32:9:32:24 | <Expr>; | ExprStmt |
136124
| stmts.kt:32:20:32:24 | break | BreakStmt |
137125
| stmts.kt:35:13:39:5 | <Label>: ... | LabeledStmt |
138-
| stmts.kt:35:13:39:5 | while (...) | WhileStmt |
139-
| stmts.kt:35:13:39:5 | { ... } | BlockStmt |
140-
| stmts.kt:35:13:39:5 | { ... } | BlockStmt |
141-
| stmts.kt:35:18:35:18 | var ...; | LocalVariableDeclStmt |
142-
| stmts.kt:35:23:35:26 | var ...; | LocalVariableDeclStmt |
126+
| stmts.kt:35:13:39:5 | for (... : ...) | EnhancedForStmt |
143127
| stmts.kt:35:29:39:5 | { ... } | BlockStmt |
144128
| stmts.kt:36:9:38:25 | do ... while (...) | DoStmt |
145129
| stmts.kt:36:9:38:25 | { ... } | BlockStmt |

0 commit comments

Comments
 (0)