Merge pull request #11014 from tamasvajk/kotlin-for-loop-var

Kotlin: Resugar `for` loops
This commit is contained in:
Tamás Vajk
2022-10-31 14:48:21 +01:00
committed by GitHub
10 changed files with 476 additions and 70 deletions

View File

@@ -1494,7 +1494,7 @@ open class KotlinFileExtractor(
}
}
private fun extractVariableExpr(v: IrVariable, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int, enclosingStmt: Label<out DbStmt>) {
private fun extractVariableExpr(v: IrVariable, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int, enclosingStmt: Label<out DbStmt>, extractInitializer: Boolean = true) {
with("variable expr", v) {
val varId = useVariable(v)
val exprId = tw.getFreshIdLabel<DbLocalvariabledeclexpr>()
@@ -1509,7 +1509,7 @@ open class KotlinFileExtractor(
tw.writeCallableEnclosingExpr(exprId, callable)
tw.writeStatementEnclosingExpr(exprId, enclosingStmt)
val i = v.initializer
if (i != null) {
if (i != null && extractInitializer) {
extractExpressionExpr(i, callable, exprId, 0, enclosingStmt)
}
if (!v.isVar) {
@@ -3181,6 +3181,90 @@ open class KotlinFileExtractor(
}
}
/**
* This method tries to extract a block as an enhanced for loop.
* It returns true if it succeeds, and false otherwise.
*/
private fun tryExtractForLoop(e: IrContainerExpression, callable: Label<out DbCallable>, parent: StmtExprParent): Boolean {
/*
* We're expecting the pattern
* {
* val iterator = [expr].iterator()
* while (iterator.hasNext()) {
* val [loopVar] = iterator.next()
* [block]
* }
* }
*/
if (e.origin != IrStatementOrigin.FOR_LOOP ||
e.statements.size != 2) {
return false
}
val iteratorVariable = e.statements[0] as? IrVariable
val innerWhile = e.statements[1] as? IrWhileLoop
if (iteratorVariable == null ||
iteratorVariable.origin != IrDeclarationOrigin.FOR_LOOP_ITERATOR ||
innerWhile == null ||
innerWhile.origin != IrStatementOrigin.FOR_LOOP_INNER_WHILE) {
return false
}
val initializer = iteratorVariable.initializer as? IrCall
if (initializer == null ||
initializer.origin != IrStatementOrigin.FOR_LOOP_ITERATOR ||
initializer.symbol.owner.name.asString() != "iterator") {
return false
}
val expr = initializer.dispatchReceiver
val cond = innerWhile.condition as? IrCall
val body = innerWhile.body as? IrBlock
if (expr == null ||
cond == null ||
cond.origin != IrStatementOrigin.FOR_LOOP_HAS_NEXT ||
(cond.dispatchReceiver as? IrGetValue)?.symbol?.owner != iteratorVariable ||
body == null ||
body.origin != IrStatementOrigin.FOR_LOOP_INNER_WHILE ||
body.statements.size < 2) {
return false
}
val loopVar = body.statements[0] as? IrVariable
val nextCall = loopVar?.initializer as? IrCall
if (loopVar == null ||
!(loopVar.origin == IrDeclarationOrigin.FOR_LOOP_VARIABLE || loopVar.origin == IrDeclarationOrigin.IR_TEMPORARY_VARIABLE) ||
nextCall == null ||
nextCall.origin != IrStatementOrigin.FOR_LOOP_NEXT ||
(nextCall.dispatchReceiver as? IrGetValue)?.symbol?.owner != iteratorVariable) {
return false
}
val id = extractLoop(innerWhile, null, parent, callable) { p, idx ->
tw.getFreshIdLabel<DbEnhancedforstmt>().also {
tw.writeStmts_enhancedforstmt(it, p, idx, callable)
}
}
extractVariableExpr(loopVar, callable, id, 0, id, extractInitializer = false)
extractExpressionExpr(expr, callable, id, 1, id)
val block = body.statements[1] as? IrBlock
if (body.statements.size == 2 && block != null) {
// Extract the body that was given to us by the compiler
extractExpressionStmt(block, callable, id, 2)
} else {
// Extract a block with all but the first (loop variable declaration) statement
extractBlock(body, body.statements.takeLast(body.statements.size - 1), id, 2, callable)
}
return true
}
/**
* This tried to extract a block as an array update.
* It returns true if it succeeds, and false otherwise.
@@ -3412,22 +3496,17 @@ open class KotlinFileExtractor(
}
}
is IrContainerExpression -> {
if(!tryExtractArrayUpdate(e, callable, parent)) {
val stmtParent = parent.stmt(e, callable)
val id = tw.getFreshIdLabel<DbBlock>()
val locId = tw.getLocation(e)
tw.writeStmts_block(id, stmtParent.parent, stmtParent.idx, callable)
tw.writeHasLocation(id, locId)
e.statements.forEachIndexed { i, s ->
extractStatement(s, callable, id, i)
}
if (!tryExtractArrayUpdate(e, callable, parent) &&
!tryExtractForLoop(e, callable, parent)) {
extractBlock(e, e.statements, parent, callable)
}
}
is IrWhileLoop -> {
extractLoop(e, parent, callable)
extractLoopWithCondition(e, parent, callable)
}
is IrDoWhileLoop -> {
extractLoop(e, parent, callable)
extractLoopWithCondition(e, parent, callable)
}
is IrInstanceInitializerCall -> {
val irConstructor = declarationStack.peek().first as? IrConstructor
@@ -3892,6 +3971,32 @@ open class KotlinFileExtractor(
}
}
private fun extractBlock(
e: IrContainerExpression,
statements: List<IrStatement>,
parent: StmtExprParent,
callable: Label<out DbCallable>
) {
val stmtParent = parent.stmt(e, callable)
extractBlock(e, statements, stmtParent.parent, stmtParent.idx, callable)
}
private fun extractBlock(
e: IrElement,
statements: List<IrStatement>,
parent: Label<out DbStmtparent>,
idx: Int,
callable: Label<out DbCallable>
) {
val id = tw.getFreshIdLabel<DbBlock>()
val locId = tw.getLocation(e)
tw.writeStmts_block(id, parent, idx, callable)
tw.writeHasLocation(id, locId)
statements.forEachIndexed { i, s ->
extractStatement(s, callable, id, i)
}
}
private inline fun <D: DeclarationDescriptor, reified B: IrSymbolOwner> getBoundSymbolOwner(symbol: IrBindableSymbol<D, B>, e: IrExpression): B? {
if (symbol.isBound) {
return symbol.owner
@@ -4000,9 +4105,11 @@ open class KotlinFileExtractor(
private fun extractLoop(
loop: IrLoop,
bodyIdx: Int?,
stmtExprParent: StmtExprParent,
callable: Label<out DbCallable>
) {
callable: Label<out DbCallable>,
getId: (Label<out DbStmtparent>, Int) -> Label<out DbStmt>
) : Label<out DbStmt> {
val stmtParent = stmtExprParent.stmt(loop, callable)
val locId = tw.getLocation(loop)
@@ -4023,22 +4130,34 @@ open class KotlinFileExtractor(
parent = stmtParent.parent
}
val id = if (loop is IrWhileLoop) {
val id = tw.getFreshIdLabel<DbWhilestmt>()
tw.writeStmts_whilestmt(id, parent, idx, callable)
id
} else {
val id = tw.getFreshIdLabel<DbDostmt>()
tw.writeStmts_dostmt(id, parent, idx, callable)
id
val id = getId(parent, idx)
tw.writeHasLocation(id, locId)
val body = loop.body
if (body != null && bodyIdx != null) {
extractExpressionStmt(body, callable, id, bodyIdx)
}
tw.writeHasLocation(id, locId)
extractExpressionExpr(loop.condition, callable, id, 0, id)
val body = loop.body
if (body != null) {
extractExpressionStmt(body, callable, id, 1)
return id
}
private fun extractLoopWithCondition(
loop: IrLoop,
stmtExprParent: StmtExprParent,
callable: Label<out DbCallable>
) {
val id = extractLoop(loop, 1, stmtExprParent, callable) { parent, idx ->
if (loop is IrWhileLoop) {
tw.getFreshIdLabel<DbWhilestmt>().also {
tw.writeStmts_whilestmt(it, parent, idx, callable)
}
} else {
tw.getFreshIdLabel<DbDostmt>().also {
tw.writeStmts_dostmt(it, parent, idx, callable)
}
}
}
extractExpressionExpr(loop.condition, callable, id, 0, id)
}
private fun IrValueParameter.isExtensionReceiver(): Boolean {

View File

@@ -1,6 +1,3 @@
| arrayIterators.kt:6:15:6:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt |
| arrayIterators.kt:7:15:7:15 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt |
| arrayIterators.kt:8:15:8:15 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt |
| arrayIterators.kt:10:16:10:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt |
| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt |
| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt |

View File

@@ -1,9 +0,0 @@
| test.kt:5:14:5:14 | hasNext(...) |
| test.kt:5:14:5:14 | iterator(...) |
| test.kt:5:14:5:14 | next(...) |
| test.kt:6:14:6:14 | hasNext(...) |
| test.kt:6:14:6:14 | iterator(...) |
| test.kt:6:14:6:14 | next(...) |
| test.kt:7:14:7:14 | hasNext(...) |
| test.kt:7:14:7:14 | iterator(...) |
| test.kt:7:14:7:14 | next(...) |

View File

@@ -0,0 +1,198 @@
stmts.kt:
# 0| [CompilationUnit] stmts
# 0| 1: [Class] StmtsKt
# 2| 1: [Method] topLevelMethod
# 2| 3: [TypeAccess] int
#-----| 4: (Parameters)
# 2| 0: [Parameter] x
# 2| 0: [TypeAccess] int
# 2| 1: [Parameter] y
# 2| 0: [TypeAccess] int
# 2| 5: [BlockStmt] { ... }
# 3| 0: [ExprStmt] <Expr>;
# 3| 0: [WhenExpr] when ...
# 3| 0: [WhenBranch] ... -> ...
# 3| 0: [GTExpr] ... > ...
# 3| 0: [VarAccess] x
# 3| 1: [VarAccess] y
# 3| 1: [BlockStmt] { ... }
# 4| 1: [WhenBranch] ... -> ...
# 4| 0: [LTExpr] ... < ...
# 4| 0: [VarAccess] x
# 4| 1: [VarAccess] y
# 4| 1: [BlockStmt] { ... }
# 5| 2: [WhenBranch] ... -> ...
# 5| 0: [BooleanLiteral] true
# 5| 1: [BlockStmt] { ... }
# 7| 1: [WhileStmt] while (...)
# 7| 0: [GTExpr] ... > ...
# 7| 0: [VarAccess] x
# 7| 1: [VarAccess] y
# 8| 1: [ReturnStmt] return ...
# 8| 0: [VarAccess] x
# 9| 2: [WhileStmt] while (...)
# 9| 0: [LTExpr] ... < ...
# 9| 0: [VarAccess] x
# 9| 1: [VarAccess] y
# 9| 1: [BlockStmt] { ... }
# 10| 0: [ReturnStmt] return ...
# 10| 0: [VarAccess] y
# 12| 3: [BlockStmt] { ... }
# 12| 0: [DoStmt] do ... while (...)
# 14| 0: [LTExpr] ... < ...
# 14| 0: [VarAccess] x
# 14| 1: [VarAccess] y
# 12| 1: [BlockStmt] { ... }
# 13| 0: [ReturnStmt] return ...
# 13| 0: [VarAccess] y
# 15| 4: [LocalVariableDeclStmt] var ...;
# 15| 1: [LocalVariableDeclExpr] z
# 15| 0: [IntegerLiteral] 3
# 17| 5: [LocalVariableDeclStmt] var ...;
# 17| 1: [LocalVariableDeclExpr] q2
# 17| 0: [WhenExpr] when ...
# 17| 0: [WhenBranch] ... -> ...
# 17| 0: [BooleanLiteral] true
# 17| 1: [BlockStmt] { ... }
# 17| 0: [ExprStmt] <Expr>;
# 17| 0: [AssignExpr] ...=...
# 17| 0: [VarAccess] z
# 17| 1: [IntegerLiteral] 4
# 17| 1: [WhenBranch] ... -> ...
# 17| 0: [BooleanLiteral] true
# 17| 1: [BlockStmt] { ... }
# 17| 0: [ExprStmt] <Expr>;
# 17| 0: [AssignExpr] ...=...
# 17| 0: [VarAccess] z
# 17| 1: [IntegerLiteral] 5
# 18| 6: [LocalVariableDeclStmt] var ...;
# 18| 1: [LocalVariableDeclExpr] q3
# 18| 0: [WhenExpr] when ...
# 18| 0: [WhenBranch] ... -> ...
# 18| 0: [BooleanLiteral] true
# 18| 1: [ExprStmt] <Expr>;
# 18| 0: [AssignExpr] ...=...
# 18| 0: [VarAccess] z
# 18| 1: [IntegerLiteral] 4
# 18| 1: [WhenBranch] ... -> ...
# 18| 0: [BooleanLiteral] true
# 18| 1: [ExprStmt] <Expr>;
# 18| 0: [AssignExpr] ...=...
# 18| 0: [VarAccess] z
# 18| 1: [IntegerLiteral] 5
# 19| 7: [ReturnStmt] return ...
# 19| 0: [AddExpr] ... + ...
# 19| 0: [VarAccess] x
# 19| 1: [VarAccess] y
# 22| 2: [Method] loops
# 22| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 22| 0: [Parameter] x
# 22| 0: [TypeAccess] int
# 22| 1: [Parameter] y
# 22| 0: [TypeAccess] int
# 22| 5: [BlockStmt] { ... }
# 23| 0: [LabeledStmt] <Label>: ...
# 23| 0: [WhileStmt] while (...)
# 23| 0: [LTExpr] ... < ...
# 23| 0: [VarAccess] x
# 23| 1: [IntegerLiteral] 100
# 23| 1: [BlockStmt] { ... }
# 24| 0: [BlockStmt] { ... }
# 24| 0: [DoStmt] do ... while (...)
# 26| 0: [GTExpr] ... > ...
# 26| 0: [VarAccess] y
# 26| 1: [IntegerLiteral] 100
# 24| 1: [BlockStmt] { ... }
# 25| 0: [ExprStmt] <Expr>;
# 25| 0: [WhenExpr] when ...
# 25| 0: [WhenBranch] ... -> ...
# 25| 0: [GTExpr] ... > ...
# 25| 0: [VarAccess] x
# 25| 1: [VarAccess] y
# 25| 1: [BreakStmt] break
# 28| 1: [WhileStmt] while (...)
# 28| 0: [GTExpr] ... > ...
# 28| 0: [VarAccess] x
# 28| 1: [VarAccess] y
# 29| 1: [ContinueStmt] continue
# 31| 2: [EnhancedForStmt] for (... : ...)
#-----| 0: (Single Local Variable Declaration)
# 31| 1: [LocalVariableDeclExpr] i
# 31| 1: [MethodAccess] rangeTo(...)
# 31| -1: [VarAccess] x
# 31| 0: [VarAccess] y
# 31| 2: [BlockStmt] { ... }
# 32| 0: [ExprStmt] <Expr>;
# 32| 0: [WhenExpr] when ...
# 32| 0: [WhenBranch] ... -> ...
# 32| 0: [GTExpr] ... > ...
# 32| 0: [VarAccess] x
# 32| 1: [VarAccess] y
# 32| 1: [BreakStmt] break
# 35| 3: [LabeledStmt] <Label>: ...
# 35| 0: [EnhancedForStmt] for (... : ...)
#-----| 0: (Single Local Variable Declaration)
# 35| 1: [LocalVariableDeclExpr] i
# 35| 1: [MethodAccess] rangeTo(...)
# 35| -1: [VarAccess] x
# 35| 0: [VarAccess] y
# 35| 2: [BlockStmt] { ... }
# 36| 0: [BlockStmt] { ... }
# 36| 0: [DoStmt] do ... while (...)
# 38| 0: [GTExpr] ... > ...
# 38| 0: [VarAccess] y
# 38| 1: [IntegerLiteral] 100
# 36| 1: [BlockStmt] { ... }
# 37| 0: [ExprStmt] <Expr>;
# 37| 0: [WhenExpr] when ...
# 37| 0: [WhenBranch] ... -> ...
# 37| 0: [GTExpr] ... > ...
# 37| 0: [VarAccess] x
# 37| 1: [VarAccess] y
# 37| 1: [BreakStmt] break
# 41| 4: [EnhancedForStmt] for (... : ...)
#-----| 0: (Single Local Variable Declaration)
# 41| 1: [LocalVariableDeclExpr] tmp3_loop_parameter
# 41| 1: [MethodAccess] withIndex(...)
# 41| -2: [TypeAccess] Integer
# 41| -1: [TypeAccess] CollectionsKt
# 41| 0: [MethodAccess] rangeTo(...)
# 41| -1: [VarAccess] x
# 41| 0: [VarAccess] y
# 41| 2: [BlockStmt] { ... }
# 41| 0: [LocalVariableDeclStmt] var ...;
# 41| 1: [LocalVariableDeclExpr] v
# 41| 0: [MethodAccess] component1(...)
# 41| -1: [VarAccess] tmp3_loop_parameter
# 41| 1: [LocalVariableDeclStmt] var ...;
# 41| 1: [LocalVariableDeclExpr] i
# 41| 0: [MethodAccess] component2(...)
# 41| -1: [VarAccess] tmp3_loop_parameter
# 41| 2: [BlockStmt] { ... }
# 42| 0: [ExprStmt] <Expr>;
# 42| 0: [WhenExpr] when ...
# 42| 0: [WhenBranch] ... -> ...
# 42| 0: [GTExpr] ... > ...
# 42| 0: [VarAccess] x
# 42| 1: [VarAccess] y
# 42| 1: [BreakStmt] break
# 46| 3: [Method] exceptions
# 46| 3: [TypeAccess] int
# 46| 5: [BlockStmt] { ... }
# 47| 0: [TryStmt] try ...
# 53| -2: [BlockStmt] { ... }
# 54| 0: [ReturnStmt] return ...
# 54| 0: [IntegerLiteral] 2
# 47| -1: [BlockStmt] { ... }
# 48| 0: [ThrowStmt] throw ...
# 48| 0: [ClassInstanceExpr] new Exception(...)
# 48| -3: [TypeAccess] Exception
# 48| 0: [StringLiteral] Foo
# 50| 0: [CatchClause] catch (...)
#-----| 0: (Single Local Variable Declaration)
# 50| 0: [TypeAccess] Exception
# 50| 1: [LocalVariableDeclExpr] e
# 50| 1: [BlockStmt] { ... }
# 51| 0: [ReturnStmt] return ...
# 51| 0: [IntegerLiteral] 1

View File

@@ -0,0 +1 @@
semmle/code/java/PrintAst.ql

View File

@@ -46,7 +46,7 @@
| stmts.kt:19:12:19:12 | x | VarAccess |
| stmts.kt:19:12:19:16 | ... + ... | AddExpr |
| stmts.kt:19:16:19:16 | y | VarAccess |
| stmts.kt:22:1:30:1 | Unit | TypeAccess |
| stmts.kt:22:1:44:1 | Unit | TypeAccess |
| stmts.kt:22:11:22:16 | int | TypeAccess |
| stmts.kt:22:19:22:24 | int | TypeAccess |
| stmts.kt:23:18:23:18 | x | VarAccess |
@@ -62,11 +62,47 @@
| stmts.kt:28:11:28:11 | x | VarAccess |
| stmts.kt:28:11:28:15 | ... > ... | GTExpr |
| stmts.kt:28:15:28:15 | y | VarAccess |
| stmts.kt:32:1:42:1 | int | TypeAccess |
| stmts.kt:34:15:34:30 | Exception | TypeAccess |
| stmts.kt:34:15:34:30 | new Exception(...) | ClassInstanceExpr |
| stmts.kt:34:26:34:28 | Foo | StringLiteral |
| stmts.kt:36:12:36:23 | Exception | TypeAccess |
| stmts.kt:36:12:36:23 | e | LocalVariableDeclExpr |
| stmts.kt:37:16:37:16 | 1 | IntegerLiteral |
| stmts.kt:40:16:40:16 | 2 | IntegerLiteral |
| stmts.kt:31:10:31:10 | i | LocalVariableDeclExpr |
| stmts.kt:31:15:31:15 | x | VarAccess |
| stmts.kt:31:15:31:18 | rangeTo(...) | MethodAccess |
| stmts.kt:31:18:31:18 | y | VarAccess |
| stmts.kt:32:9:32:24 | when ... | WhenExpr |
| stmts.kt:32:13:32:13 | x | VarAccess |
| stmts.kt:32:13:32:17 | ... > ... | GTExpr |
| stmts.kt:32:17:32:17 | y | VarAccess |
| stmts.kt:35:18:35:18 | i | LocalVariableDeclExpr |
| stmts.kt:35:23:35:23 | x | VarAccess |
| stmts.kt:35:23:35:26 | rangeTo(...) | MethodAccess |
| stmts.kt:35:26:35:26 | y | VarAccess |
| stmts.kt:37:13:37:36 | when ... | WhenExpr |
| stmts.kt:37:17:37:17 | x | VarAccess |
| stmts.kt:37:17:37:21 | ... > ... | GTExpr |
| stmts.kt:37:21:37:21 | y | VarAccess |
| stmts.kt:38:18:38:18 | y | VarAccess |
| stmts.kt:38:18:38:24 | ... > ... | GTExpr |
| stmts.kt:38:22:38:24 | 100 | IntegerLiteral |
| stmts.kt:41:11:41:11 | component1(...) | MethodAccess |
| stmts.kt:41:11:41:11 | v | LocalVariableDeclExpr |
| stmts.kt:41:13:41:13 | component2(...) | MethodAccess |
| stmts.kt:41:13:41:13 | i | LocalVariableDeclExpr |
| stmts.kt:41:19:41:36 | tmp3_loop_parameter | LocalVariableDeclExpr |
| stmts.kt:41:19:41:36 | tmp3_loop_parameter | VarAccess |
| stmts.kt:41:19:41:36 | tmp3_loop_parameter | VarAccess |
| stmts.kt:41:20:41:20 | x | VarAccess |
| stmts.kt:41:20:41:23 | rangeTo(...) | MethodAccess |
| stmts.kt:41:23:41:23 | y | VarAccess |
| stmts.kt:41:26:41:36 | CollectionsKt | TypeAccess |
| stmts.kt:41:26:41:36 | Integer | TypeAccess |
| stmts.kt:41:26:41:36 | withIndex(...) | MethodAccess |
| stmts.kt:42:9:42:24 | when ... | WhenExpr |
| stmts.kt:42:13:42:13 | x | VarAccess |
| stmts.kt:42:13:42:17 | ... > ... | GTExpr |
| stmts.kt:42:17:42:17 | y | VarAccess |
| stmts.kt:46:1:56:1 | int | TypeAccess |
| stmts.kt:48:15:48:30 | Exception | TypeAccess |
| stmts.kt:48:15:48:30 | new Exception(...) | ClassInstanceExpr |
| stmts.kt:48:26:48:28 | Foo | StringLiteral |
| stmts.kt:50:12:50:23 | Exception | TypeAccess |
| stmts.kt:50:12:50:23 | e | LocalVariableDeclExpr |
| stmts.kt:51:16:51:16 | 1 | IntegerLiteral |
| stmts.kt:54:16:54:16 | 2 | IntegerLiteral |

View File

@@ -1,6 +1,10 @@
breakLabel
| stmts.kt:25:24:25:33 | break | loop |
| stmts.kt:37:24:37:36 | break | forLoop |
continueLabel
jumpTarget
| stmts.kt:25:24:25:33 | break | stmts.kt:23:11:27:5 | while (...) |
| stmts.kt:29:9:29:16 | continue | stmts.kt:28:5:29:16 | while (...) |
| stmts.kt:32:20:32:24 | break | stmts.kt:31:5:33:5 | for (... : ...) |
| stmts.kt:37:24:37:36 | break | stmts.kt:35:13:39:5 | for (... : ...) |
| stmts.kt:42:20:42:24 | break | stmts.kt:41:5:43:5 | for (... : ...) |

View File

@@ -29,7 +29,7 @@ enclosing
| stmts.kt:18:37:18:37 | <Expr>; | stmts.kt:18:26:18:56 | ... -> ... |
| stmts.kt:18:52:18:52 | <Expr>; | stmts.kt:18:26:18:56 | ... -> ... |
| stmts.kt:19:5:19:16 | return ... | stmts.kt:2:41:20:1 | { ... } |
| stmts.kt:23:11:27:5 | <Label>: ... | stmts.kt:22:27:30:1 | { ... } |
| stmts.kt:23:11:27:5 | <Label>: ... | stmts.kt:22:27:44:1 | { ... } |
| stmts.kt:23:11:27:5 | while (...) | stmts.kt:23:11:27:5 | <Label>: ... |
| stmts.kt:23:27:27:5 | { ... } | stmts.kt:23:11:27:5 | while (...) |
| stmts.kt:24:9:26:25 | do ... while (...) | stmts.kt:24:9:26:25 | { ... } |
@@ -38,16 +38,38 @@ enclosing
| stmts.kt:25:13:25:33 | ... -> ... | stmts.kt:25:13:25:33 | <Expr>; |
| stmts.kt:25:13:25:33 | <Expr>; | stmts.kt:24:13:26:9 | { ... } |
| stmts.kt:25:24:25:33 | break | stmts.kt:25:13:25:33 | ... -> ... |
| stmts.kt:28:5:29:16 | while (...) | stmts.kt:22:27:30:1 | { ... } |
| stmts.kt:28:5:29:16 | while (...) | stmts.kt:22:27:44:1 | { ... } |
| stmts.kt:29:9:29:16 | continue | stmts.kt:28:5:29:16 | while (...) |
| stmts.kt:33:5:41:5 | try ... | stmts.kt:32:23:42:1 | { ... } |
| stmts.kt:33:9:35:5 | { ... } | stmts.kt:33:5:41:5 | try ... |
| stmts.kt:34:9:34:30 | throw ... | stmts.kt:33:9:35:5 | { ... } |
| stmts.kt:36:5:38:5 | catch (...) | stmts.kt:33:5:41:5 | try ... |
| stmts.kt:36:26:38:5 | { ... } | stmts.kt:36:5:38:5 | catch (...) |
| stmts.kt:37:9:37:16 | return ... | stmts.kt:36:26:38:5 | { ... } |
| stmts.kt:39:13:41:5 | { ... } | stmts.kt:33:5:41:5 | try ... |
| stmts.kt:40:9:40:16 | return ... | stmts.kt:39:13:41:5 | { ... } |
| stmts.kt:31:5:33:5 | for (... : ...) | stmts.kt:22:27:44:1 | { ... } |
| stmts.kt:31:21:33:5 | { ... } | stmts.kt:31:5:33:5 | for (... : ...) |
| stmts.kt:32:9:32:24 | ... -> ... | stmts.kt:32:9:32:24 | <Expr>; |
| stmts.kt:32:9:32:24 | <Expr>; | stmts.kt:31:21:33:5 | { ... } |
| stmts.kt:32:20:32:24 | break | stmts.kt:32:9:32:24 | ... -> ... |
| stmts.kt:35:13:39:5 | <Label>: ... | stmts.kt:22:27:44:1 | { ... } |
| stmts.kt:35:13:39:5 | for (... : ...) | stmts.kt:35:13:39:5 | <Label>: ... |
| stmts.kt:35:29:39:5 | { ... } | stmts.kt:35:13:39:5 | for (... : ...) |
| stmts.kt:36:9:38:25 | do ... while (...) | stmts.kt:36:9:38:25 | { ... } |
| stmts.kt:36:9:38:25 | { ... } | stmts.kt:35:29:39:5 | { ... } |
| stmts.kt:36:13:38:9 | { ... } | stmts.kt:36:9:38:25 | do ... while (...) |
| stmts.kt:37:13:37:36 | ... -> ... | stmts.kt:37:13:37:36 | <Expr>; |
| stmts.kt:37:13:37:36 | <Expr>; | stmts.kt:36:13:38:9 | { ... } |
| stmts.kt:37:24:37:36 | break | stmts.kt:37:13:37:36 | ... -> ... |
| stmts.kt:41:5:43:5 | for (... : ...) | stmts.kt:22:27:44:1 | { ... } |
| stmts.kt:41:5:43:5 | { ... } | stmts.kt:41:5:43:5 | for (... : ...) |
| stmts.kt:41:11:41:11 | var ...; | stmts.kt:41:5:43:5 | { ... } |
| stmts.kt:41:13:41:13 | var ...; | stmts.kt:41:5:43:5 | { ... } |
| stmts.kt:41:39:43:5 | { ... } | stmts.kt:41:5:43:5 | { ... } |
| stmts.kt:42:9:42:24 | ... -> ... | stmts.kt:42:9:42:24 | <Expr>; |
| stmts.kt:42:9:42:24 | <Expr>; | stmts.kt:41:39:43:5 | { ... } |
| stmts.kt:42:20:42:24 | break | stmts.kt:42:9:42:24 | ... -> ... |
| stmts.kt:47:5:55:5 | try ... | stmts.kt:46:23:56:1 | { ... } |
| stmts.kt:47:9:49:5 | { ... } | stmts.kt:47:5:55:5 | try ... |
| stmts.kt:48:9:48:30 | throw ... | stmts.kt:47:9:49:5 | { ... } |
| stmts.kt:50:5:52:5 | catch (...) | stmts.kt:47:5:55:5 | try ... |
| stmts.kt:50:26:52:5 | { ... } | stmts.kt:50:5:52:5 | catch (...) |
| stmts.kt:51:9:51:16 | return ... | stmts.kt:50:26:52:5 | { ... } |
| stmts.kt:53:13:55:5 | { ... } | stmts.kt:47:5:55:5 | try ... |
| stmts.kt:54:9:54:16 | return ... | stmts.kt:53:13:55:5 | { ... } |
#select
| stmts.kt:2:41:20:1 | { ... } | BlockStmt |
| stmts.kt:3:5:6:5 | <Expr>; | ExprStmt |
@@ -80,7 +102,7 @@ enclosing
| stmts.kt:18:37:18:37 | <Expr>; | ExprStmt |
| stmts.kt:18:52:18:52 | <Expr>; | ExprStmt |
| stmts.kt:19:5:19:16 | return ... | ReturnStmt |
| stmts.kt:22:27:30:1 | { ... } | BlockStmt |
| stmts.kt:22:27:44:1 | { ... } | BlockStmt |
| stmts.kt:23:11:27:5 | <Label>: ... | LabeledStmt |
| stmts.kt:23:11:27:5 | while (...) | WhileStmt |
| stmts.kt:23:27:27:5 | { ... } | BlockStmt |
@@ -92,12 +114,34 @@ enclosing
| stmts.kt:25:24:25:33 | break | BreakStmt |
| stmts.kt:28:5:29:16 | while (...) | WhileStmt |
| stmts.kt:29:9:29:16 | continue | ContinueStmt |
| stmts.kt:32:23:42:1 | { ... } | BlockStmt |
| stmts.kt:33:5:41:5 | try ... | TryStmt |
| stmts.kt:33:9:35:5 | { ... } | BlockStmt |
| stmts.kt:34:9:34:30 | throw ... | ThrowStmt |
| stmts.kt:36:5:38:5 | catch (...) | CatchClause |
| stmts.kt:36:26:38:5 | { ... } | BlockStmt |
| stmts.kt:37:9:37:16 | return ... | ReturnStmt |
| stmts.kt:39:13:41:5 | { ... } | BlockStmt |
| stmts.kt:40:9:40:16 | return ... | ReturnStmt |
| stmts.kt:31:5:33:5 | for (... : ...) | EnhancedForStmt |
| stmts.kt:31:21:33:5 | { ... } | BlockStmt |
| stmts.kt:32:9:32:24 | ... -> ... | WhenBranch |
| stmts.kt:32:9:32:24 | <Expr>; | ExprStmt |
| stmts.kt:32:20:32:24 | break | BreakStmt |
| stmts.kt:35:13:39:5 | <Label>: ... | LabeledStmt |
| stmts.kt:35:13:39:5 | for (... : ...) | EnhancedForStmt |
| stmts.kt:35:29:39:5 | { ... } | BlockStmt |
| stmts.kt:36:9:38:25 | do ... while (...) | DoStmt |
| stmts.kt:36:9:38:25 | { ... } | BlockStmt |
| stmts.kt:36:13:38:9 | { ... } | BlockStmt |
| stmts.kt:37:13:37:36 | ... -> ... | WhenBranch |
| stmts.kt:37:13:37:36 | <Expr>; | ExprStmt |
| stmts.kt:37:24:37:36 | break | BreakStmt |
| stmts.kt:41:5:43:5 | for (... : ...) | EnhancedForStmt |
| stmts.kt:41:5:43:5 | { ... } | BlockStmt |
| stmts.kt:41:11:41:11 | var ...; | LocalVariableDeclStmt |
| stmts.kt:41:13:41:13 | var ...; | LocalVariableDeclStmt |
| stmts.kt:41:39:43:5 | { ... } | BlockStmt |
| stmts.kt:42:9:42:24 | ... -> ... | WhenBranch |
| stmts.kt:42:9:42:24 | <Expr>; | ExprStmt |
| stmts.kt:42:20:42:24 | break | BreakStmt |
| stmts.kt:46:23:56:1 | { ... } | BlockStmt |
| stmts.kt:47:5:55:5 | try ... | TryStmt |
| stmts.kt:47:9:49:5 | { ... } | BlockStmt |
| stmts.kt:48:9:48:30 | throw ... | ThrowStmt |
| stmts.kt:50:5:52:5 | catch (...) | CatchClause |
| stmts.kt:50:26:52:5 | { ... } | BlockStmt |
| stmts.kt:51:9:51:16 | return ... | ReturnStmt |
| stmts.kt:53:13:55:5 | { ... } | BlockStmt |
| stmts.kt:54:9:54:16 | return ... | ReturnStmt |

View File

@@ -27,6 +27,20 @@ fun loops(x: Int, y: Int) {
}
while(x > y)
continue
for (i in x..y) {
if (x > y) break
}
forLoop@for (i in x..y) {
do {
if (x > y) break@forLoop
} while (y > 100)
}
for ((v,i) in (x..y).withIndex()) {
if (x > y) break
}
}
fun exceptions(): Int {
@@ -40,3 +54,5 @@ fun exceptions(): Int {
return 2
}
}
// Diagnostic Matches: % Couldn't find a Java equivalent function to kotlin.Int.rangeTo in java.lang.Integer%

View File

@@ -1 +1 @@
| stmts.kt:33:5:41:5 | try ... | stmts.kt:33:9:35:5 | { ... } |
| stmts.kt:47:5:55:5 | try ... | stmts.kt:47:9:49:5 | { ... } |