Skip to content

Commit a6e44ed

Browse files
committed
Kotlin: extract suspend modifier and handle suspend SAM conversions
1 parent 3e58605 commit a6e44ed

File tree

7 files changed

+103
-9
lines changed

7 files changed

+103
-9
lines changed

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

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,9 @@ open class KotlinFileExtractor(
910910
if (f is IrSimpleFunction && f.overriddenSymbols.isNotEmpty()) {
911911
addModifiers(id, "override")
912912
}
913+
if (f.isSuspend) {
914+
addModifiers(id, "suspend")
915+
}
913916

914917
return id
915918
}
@@ -1461,7 +1464,7 @@ open class KotlinFileExtractor(
14611464

14621465
val (isFunctionInvoke, isBigArityFunctionInvoke) =
14631466
if (drType is IrSimpleType &&
1464-
drType.isFunctionOrKFunction() &&
1467+
(drType.isFunctionOrKFunction() || drType.isSuspendFunctionOrKFunction()) &&
14651468
callTarget.name.asString() == OperatorNameConventions.INVOKE.asString()) {
14661469
Pair(true, drType.arguments.size > BuiltInFunctionArity.BIG_ARITY)
14671470
} else {
@@ -4516,17 +4519,17 @@ open class KotlinFileExtractor(
45164519
```
45174520
*/
45184521

4519-
if (!e.argument.type.isFunctionOrKFunction()) {
4520-
logger.errorElement("Expected to find expression with function type in SAM conversion.", e)
4521-
return
4522-
}
4523-
45244522
val st = e.argument.type as? IrSimpleType
45254523
if (st == null) {
45264524
logger.errorElement("Expected to find a simple type in SAM conversion.", e)
45274525
return
45284526
}
45294527

4528+
if (!st.isFunctionOrKFunction() && !st.isSuspendFunctionOrKFunction()) {
4529+
logger.errorElement("Expected to find expression with function type in SAM conversion.", e)
4530+
return
4531+
}
4532+
45304533
// Either Function1, ... Function22 or FunctionN type, but not Function23 or above.
45314534
val functionType = getFunctionalInterfaceTypeWithTypeArgs(st.arguments)
45324535
if (functionType == null) {
@@ -4589,6 +4592,10 @@ open class KotlinFileExtractor(
45894592
// the real underlying R Function<T, R>.apply(T t).
45904593
forceExtractFunction(samMember, classId, extractBody = false, extractMethodAndParameterTypeAccesses = true, typeSub, classTypeArgs, ids.function, tw.getLocation(e))
45914594

4595+
if (st.isSuspendFunctionOrKFunction()) {
4596+
addModifiers(ids.function, "suspend")
4597+
}
4598+
45924599
//body
45934600
val blockId = tw.getFreshIdLabel<DbBlock>()
45944601
tw.writeStmts_block(blockId, ids.function, 0, ids.function)

java/ql/lib/semmle/code/java/Modifier.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ abstract class Modifiable extends Element {
6767
/** Holds if this element has an `inline` modifier. */
6868
predicate isInline() { this.hasModifier("inline") }
6969

70+
/** Holds if this element has a `suspend` modifier. */
71+
predicate isSuspend() { this.hasModifier("suspend") }
72+
7073
/** Holds if this element has a `volatile` modifier. */
7174
predicate isVolatile() { this.hasModifier("volatile") }
7275

java/ql/test/kotlin/library-tests/dataflow/func/test.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@
1818
| localFunction.kt:13:32:13:38 | taint(...) | localFunction.kt:13:21:13:39 | fn4(...) |
1919
| samConversion.kt:11:37:11:43 | taint(...) | samConversion.kt:14:24:14:29 | go(...) |
2020
| samConversion.kt:15:34:15:40 | taint(...) | samConversion.kt:15:24:15:41 | go(...) |
21+
| samConversion.kt:17:41:17:47 | taint(...) | samConversion.kt:20:24:20:29 | go(...) |
22+
| samConversion.kt:21:34:21:40 | taint(...) | samConversion.kt:21:24:21:41 | go(...) |

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6265,6 +6265,58 @@ samConversion.kt:
62656265
# 57| 5: [BlockStmt] { ... }
62666266
# 58| 0: [LocalVariableDeclStmt] var ...;
62676267
# 58| 1: [LocalVariableDeclExpr] i0
6268+
# 58| 0: [CastExpr] (...)...
6269+
# 58| 0: [TypeAccess] InterfaceFn1Sus
6270+
# 58| 1: [ClassInstanceExpr] new (...)
6271+
# 58| -4: [AnonymousClass] new InterfaceFn1Sus(...) { ... }
6272+
# 58| 1: [Constructor]
6273+
#-----| 4: (Parameters)
6274+
# 58| 0: [Parameter] <fn>
6275+
# 58| 5: [BlockStmt] { ... }
6276+
# 58| 0: [SuperConstructorInvocationStmt] super(...)
6277+
# 58| 1: [ExprStmt] <Expr>;
6278+
# 58| 0: [AssignExpr] ...=...
6279+
# 58| 0: [VarAccess] this.<fn>
6280+
# 58| -1: [ThisAccess] this
6281+
# 58| 1: [VarAccess] <fn>
6282+
# 58| 2: [FieldDeclaration] Function2<Integer,Integer,Unit> <fn>;
6283+
# 58| -1: [TypeAccess] Function2<Integer,Integer,Unit>
6284+
# 58| 0: [TypeAccess] Integer
6285+
# 58| 1: [TypeAccess] Integer
6286+
# 58| 2: [TypeAccess] Unit
6287+
# 58| 3: [Method] fn1
6288+
# 58| 3: [TypeAccess] Unit
6289+
#-----| 4: (Parameters)
6290+
# 58| 0: [Parameter] i
6291+
# 58| 0: [TypeAccess] int
6292+
# 58| 1: [Parameter] j
6293+
# 58| 0: [TypeAccess] int
6294+
# 58| 5: [BlockStmt] { ... }
6295+
# 58| 0: [ReturnStmt] return ...
6296+
# 58| 0: [MethodAccess] invoke(...)
6297+
# 58| -1: [VarAccess] <fn>
6298+
# 58| 0: [VarAccess] i
6299+
# 58| 1: [VarAccess] j
6300+
# 58| -3: [TypeAccess] InterfaceFn1Sus
6301+
# 58| 0: [LambdaExpr] ...->...
6302+
# 58| -4: [AnonymousClass] new Function2<Integer,Integer,Unit>(...) { ... }
6303+
# 58| 1: [Constructor]
6304+
# 58| 5: [BlockStmt] { ... }
6305+
# 58| 0: [SuperConstructorInvocationStmt] super(...)
6306+
# 58| 2: [Method] invoke
6307+
# 58| 3: [TypeAccess] Unit
6308+
#-----| 4: (Parameters)
6309+
# 58| 0: [Parameter] a
6310+
# 58| 0: [TypeAccess] int
6311+
# 58| 1: [Parameter] b
6312+
# 58| 0: [TypeAccess] int
6313+
# 58| 5: [BlockStmt] { ... }
6314+
# 58| 0: [ExprStmt] <Expr>;
6315+
# 58| 0: [VarAccess] INSTANCE
6316+
# 58| -3: [TypeAccess] Function2<Integer,Integer,Unit>
6317+
# 58| 0: [TypeAccess] Integer
6318+
# 58| 1: [TypeAccess] Integer
6319+
# 58| 2: [TypeAccess] Unit
62686320
# 59| 1: [ExprStmt] <Expr>;
62696321
# 59| 0: [MethodAccess] fn1(...)
62706322
# 59| -1: [VarAccess] i0

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3919,6 +3919,34 @@
39193919
| samConversion.kt:54:29:54:34 | int | file://:0:0:0:0 | <none> | TypeAccess |
39203920
| samConversion.kt:57:9:60:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
39213921
| samConversion.kt:58:5:58:45 | i0 | samConversion.kt:57:9:60:1 | test | LocalVariableDeclExpr |
3922+
| samConversion.kt:58:14:58:45 | (...)... | samConversion.kt:57:9:60:1 | test | CastExpr |
3923+
| samConversion.kt:58:14:58:45 | ...=... | samConversion.kt:58:14:58:45 | | AssignExpr |
3924+
| samConversion.kt:58:14:58:45 | <fn> | samConversion.kt:58:14:58:45 | | VarAccess |
3925+
| samConversion.kt:58:14:58:45 | <fn> | samConversion.kt:58:14:58:45 | fn1 | VarAccess |
3926+
| samConversion.kt:58:14:58:45 | Function2<Integer,Integer,Unit> | file://:0:0:0:0 | <none> | TypeAccess |
3927+
| samConversion.kt:58:14:58:45 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
3928+
| samConversion.kt:58:14:58:45 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
3929+
| samConversion.kt:58:14:58:45 | InterfaceFn1Sus | samConversion.kt:57:9:60:1 | test | TypeAccess |
3930+
| samConversion.kt:58:14:58:45 | InterfaceFn1Sus | samConversion.kt:57:9:60:1 | test | TypeAccess |
3931+
| samConversion.kt:58:14:58:45 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
3932+
| samConversion.kt:58:14:58:45 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
3933+
| samConversion.kt:58:14:58:45 | i | samConversion.kt:58:14:58:45 | fn1 | VarAccess |
3934+
| samConversion.kt:58:14:58:45 | int | file://:0:0:0:0 | <none> | TypeAccess |
3935+
| samConversion.kt:58:14:58:45 | int | file://:0:0:0:0 | <none> | TypeAccess |
3936+
| samConversion.kt:58:14:58:45 | invoke(...) | samConversion.kt:58:14:58:45 | fn1 | MethodAccess |
3937+
| samConversion.kt:58:14:58:45 | j | samConversion.kt:58:14:58:45 | fn1 | VarAccess |
3938+
| samConversion.kt:58:14:58:45 | new (...) | samConversion.kt:57:9:60:1 | test | ClassInstanceExpr |
3939+
| samConversion.kt:58:14:58:45 | this | samConversion.kt:58:14:58:45 | | ThisAccess |
3940+
| samConversion.kt:58:14:58:45 | this.<fn> | samConversion.kt:58:14:58:45 | | VarAccess |
3941+
| samConversion.kt:58:30:58:45 | ...->... | samConversion.kt:57:9:60:1 | test | LambdaExpr |
3942+
| samConversion.kt:58:30:58:45 | Function2<Integer,Integer,Unit> | samConversion.kt:57:9:60:1 | test | TypeAccess |
3943+
| samConversion.kt:58:30:58:45 | Integer | samConversion.kt:57:9:60:1 | test | TypeAccess |
3944+
| samConversion.kt:58:30:58:45 | Integer | samConversion.kt:57:9:60:1 | test | TypeAccess |
3945+
| samConversion.kt:58:30:58:45 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
3946+
| samConversion.kt:58:30:58:45 | Unit | samConversion.kt:57:9:60:1 | test | TypeAccess |
3947+
| samConversion.kt:58:32:58:32 | int | file://:0:0:0:0 | <none> | TypeAccess |
3948+
| samConversion.kt:58:35:58:35 | int | file://:0:0:0:0 | <none> | TypeAccess |
3949+
| samConversion.kt:58:40:58:43 | INSTANCE | samConversion.kt:58:30:58:45 | invoke | VarAccess |
39223950
| samConversion.kt:59:5:59:6 | i0 | samConversion.kt:57:9:60:1 | test | VarAccess |
39233951
| samConversion.kt:59:8:59:15 | fn1(...) | samConversion.kt:57:9:60:1 | test | MethodAccess |
39243952
| samConversion.kt:59:12:59:12 | 1 | samConversion.kt:57:9:60:1 | test | IntegerLiteral |

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ lambdaExpr
2626
| samConversion.kt:11:12:13:5 | ...->... | stmt body | samConversion.kt:11:12:13:5 | invoke | invoke(int) | samConversion.kt:11:12:13:5 | new Function1<Integer,Boolean>(...) { ... } |
2727
| samConversion.kt:43:31:45:68 | ...->... | stmt body | samConversion.kt:43:31:45:68 | invoke | invoke(int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int) | samConversion.kt:43:31:45:68 | new FunctionN<Boolean>(...) { ... } |
2828
| samConversion.kt:46:32:46:44 | ...->... | stmt body | samConversion.kt:46:32:46:44 | invoke | invoke(int) | samConversion.kt:46:32:46:44 | new Function1<Integer,Boolean>(...) { ... } |
29+
| samConversion.kt:58:30:58:45 | ...->... | stmt body | samConversion.kt:58:30:58:45 | invoke | invoke(int,int) | samConversion.kt:58:30:58:45 | new Function2<Integer,Integer,Unit>(...) { ... } |
2930
memberRefExprs
3031
| funcExprs.kt:38:26:38:38 | ...::... | funcExprs.kt:38:26:38:38 | invoke | invoke() | funcExprs.kt:38:26:38:38 | new Function0<Integer>(...) { ... } |
3132
| funcExprs.kt:39:26:39:36 | ...::... | funcExprs.kt:39:26:39:36 | invoke | invoke() | funcExprs.kt:39:26:39:36 | new Function0<Integer>(...) { ... } |
@@ -60,10 +61,10 @@ modifiers
6061
| funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | public |
6162
| funcExprs.kt:75:12:75:22 | ...->... | funcExprs.kt:75:12:75:22 | invoke | override, public |
6263
| funcExprs.kt:83:31:83:51 | ...->... | funcExprs.kt:83:31:83:51 | invoke | override, public |
63-
| funcExprs.kt:86:39:86:59 | ...->... | funcExprs.kt:86:39:86:59 | invoke | override, public |
64+
| funcExprs.kt:86:39:86:59 | ...->... | funcExprs.kt:86:39:86:59 | invoke | override, public, suspend |
6465
| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | override, public |
6566
| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | public |
66-
| funcExprs.kt:94:15:94:67 | ...->... | funcExprs.kt:94:15:94:67 | invoke | override, public |
67+
| funcExprs.kt:94:15:94:67 | ...->... | funcExprs.kt:94:15:94:67 | invoke | override, public, suspend |
6768
| samConversion.kt:2:31:2:45 | ...->... | samConversion.kt:2:31:2:45 | invoke | override, public |
6869
| samConversion.kt:4:27:4:42 | ...->... | samConversion.kt:4:27:4:42 | invoke | override, public |
6970
| samConversion.kt:7:29:7:46 | ...->... | samConversion.kt:7:29:7:46 | invoke | override, public |
@@ -72,6 +73,7 @@ modifiers
7273
| samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | override, public |
7374
| samConversion.kt:43:31:45:68 | ...->... | samConversion.kt:43:31:45:68 | invoke | public |
7475
| samConversion.kt:46:32:46:44 | ...->... | samConversion.kt:46:32:46:44 | invoke | override, public |
76+
| samConversion.kt:58:30:58:45 | ...->... | samConversion.kt:58:30:58:45 | invoke | override, public, suspend |
7577
nonOverrideInvoke
7678
| funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | 23 |
7779
| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | 23 |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ methods
3636
| methods5.kt:0:0:0:0 | Methods5Kt | methods5.kt:3:1:11:1 | x | x() | public, static | |
3737
| methods5.kt:5:3:5:27 | | methods5.kt:5:3:5:27 | a | a(int) | public | |
3838
| methods5.kt:9:3:9:32 | | methods5.kt:9:3:9:32 | f1 | f1(foo.bar.C1,int) | public | |
39-
| methods6.kt:0:0:0:0 | Methods6Kt | methods6.kt:3:9:4:1 | s | s() | public, static | |
39+
| methods6.kt:0:0:0:0 | Methods6Kt | methods6.kt:3:9:4:1 | s | s() | public, static, suspend | |
4040
| methods.kt:0:0:0:0 | MethodsKt | methods.kt:2:1:3:1 | topLevelMethod | topLevelMethod(int,int) | public, static | |
4141
| methods.kt:5:1:20:1 | Class | methods.kt:6:5:7:5 | classMethod | classMethod(int,int) | public | |
4242
| methods.kt:5:1:20:1 | Class | methods.kt:9:5:12:5 | anotherClassMethod | anotherClassMethod(int,int) | public | |

0 commit comments

Comments
 (0)