Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 87f2fd0

Browse files
authored
Merge pull request #360 from github/kotlin-adapter-functions
Extract adapter functions in an identifiable way
2 parents 468a34d + 9954158 commit 87f2fd0

11 files changed

Lines changed: 92 additions & 1 deletion

File tree

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,10 @@ open class KotlinFileExtractor(
943943
extractLocalTypeDeclStmt(classId, s, callable, parent, idx)
944944
val ids = getLocallyVisibleFunctionLabels(s)
945945
tw.writeKtLocalFunction(ids.function)
946+
947+
if (s.origin == IrDeclarationOrigin.ADAPTER_FOR_CALLABLE_REFERENCE) {
948+
tw.writeCompiler_generated(classId, 1)
949+
}
946950
} else {
947951
logger.errorElement("Expected to find local function", s)
948952
}

java/ql/lib/config/semmlecode.dbscheme

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,3 +1221,9 @@ ktPropertyDelegates(
12211221
unique int id: @kt_property ref,
12221222
unique int variableId: @variable ref
12231223
)
1224+
1225+
compiler_generated(
1226+
unique int id: @element ref,
1227+
int kind: int ref
1228+
// 1: Declaring classes of adapter functions in Kotlin
1229+
)

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ class Element extends @element, Top {
4141

4242
/** Cast this element to a `Documentable`. */
4343
Documentable getDoc() { result = this }
44+
45+
/** Holds if this is an auxiliary program element generated by the compiler. */
46+
predicate isCompilerGenerated() { compiler_generated(this, _) }
4447
}
4548

4649
/**

java/ql/src/Violations of Best Practice/Dead Code/DeadRefTypes.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ predicate dead(RefType dead) {
5050
// Exclude classes that look like they may be reflectively constructed.
5151
not dead.getAnAnnotation() instanceof ReflectiveAccessAnnotation and
5252
// Insist all source ancestors are dead as well.
53-
forall(RefType t | t.fromSource() and t = getASuperTypePlus(dead) | dead(t))
53+
forall(RefType t | t.fromSource() and t = getASuperTypePlus(dead) | dead(t)) and
54+
// Exclude compiler generated classes (e.g. declaring type of adapter functions in Kotlin)
55+
not dead.isCompilerGenerated()
5456
}
5557

5658
from RefType t, string kind

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,49 @@ reflection.kt:
206206
# 103| 0: [Parameter] l
207207
# 103| 1: [Parameter] l2
208208
# 103| 5: [BlockStmt] { ... }
209+
# 121| 9: [Method] fn1
210+
# 121| 5: [BlockStmt] { ... }
211+
# 121| 0: [ReturnStmt] return ...
212+
# 121| 0: [IntegerLiteral] 5
213+
# 123| 10: [Method] fn2
214+
#-----| 4: (Parameters)
215+
# 123| 0: [Parameter] f
216+
# 123| 5: [BlockStmt] { ... }
217+
# 123| 0: [ReturnStmt] return ...
218+
# 123| 0: [MethodAccess] invoke(...)
219+
# 123| -1: [VarAccess] f
220+
# 125| 11: [Method] adapted
221+
# 125| 5: [BlockStmt] { ... }
222+
# 126| 0: [ExprStmt] <Expr>;
223+
# 126| 0: [MethodAccess] fn2(...)
224+
# 126| -1: [TypeAccess] ReflectionKt
225+
# 126| 0: [StmtExpr] <Stmt>
226+
# 126| 0: [BlockStmt] { ... }
227+
# 126| 0: [LocalTypeDeclStmt] class ...
228+
# 126| 0: [LocalClass]
229+
# 126| 1: [Constructor]
230+
# 126| 5: [BlockStmt] { ... }
231+
# 126| 0: [SuperConstructorInvocationStmt] super(...)
232+
# 126| 1: [Method] fn1
233+
# 126| 5: [BlockStmt] { ... }
234+
# 126| 0: [ExprStmt] <Expr>;
235+
# 126| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
236+
# 126| 0: [TypeAccess] Unit
237+
# 126| 1: [MethodAccess] fn1(...)
238+
# 126| -1: [TypeAccess] ReflectionKt
239+
# 126| 1: [ExprStmt] <Expr>;
240+
# 126| 0: [MemberRefExpr] ...::...
241+
# 126| -4: [AnonymousClass] new Function0<Unit>(...) { ... }
242+
# 126| 1: [Constructor]
243+
# 126| 5: [BlockStmt] { ... }
244+
# 126| 0: [SuperConstructorInvocationStmt] super(...)
245+
# 126| 1: [Method] invoke
246+
# 126| 5: [BlockStmt] { ... }
247+
# 126| 0: [ReturnStmt] return ...
248+
# 126| 0: [MethodAccess] fn1(...)
249+
# 126| -1: [TypeAccess] ReflectionKt
250+
# 126| -3: [TypeAccess] Function0<Unit>
251+
# 126| 0: [TypeAccess] Unit
209252
# 5| 2: [Class] Reflection
210253
# 5| 1: [Constructor] Reflection
211254
# 5| 5: [BlockStmt] { ... }

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ functionReferences
5151
| reflection.kt:98:14:98:17 | ...::... | reflection.kt:98:14:98:17 | invoke | reflection.kt:94:1:94:24 | fn |
5252
| reflection.kt:99:14:99:29 | ...::... | reflection.kt:99:14:99:29 | invoke | file://<external>/Class2$Inner.class:0:0:0:0 | Inner<String> |
5353
| reflection.kt:116:40:116:44 | ...::... | reflection.kt:116:40:116:44 | invoke | reflection.kt:115:9:115:27 | fn1 |
54+
| reflection.kt:126:9:126:13 | ...::... | reflection.kt:126:9:126:13 | invoke | reflection.kt:121:1:121:13 | fn1 |
5455
propertyGetReferences
5556
| reflection.kt:10:38:10:42 | ...::... | reflection.kt:10:38:10:42 | get | reflection.kt:33:9:33:23 | getP0 |
5657
| reflection.kt:15:35:15:41 | ...::... | reflection.kt:15:35:15:41 | get | reflection.kt:33:9:33:23 | getP0 |
@@ -114,6 +115,7 @@ callsInsideInvocationMethods
114115
| reflection.kt:109:17:109:27 | ...::... | reflection.kt:109:17:109:27 | new KMutableProperty0<Integer>(...) { ... } | reflection.kt:109:17:109:27 | set | reflection.kt:109:17:109:27 | setProp1(...) | Base1.setProp1 |
115116
| reflection.kt:116:40:116:44 | ...::... | reflection.kt:116:40:116:44 | new Function1<Integer,Unit>(...) { ... } | reflection.kt:116:40:116:44 | invoke | reflection.kt:116:40:116:44 | fn1(...) | .fn1 |
116117
| reflection.kt:116:40:116:44 | ...::... | reflection.kt:116:40:116:44 | new Function1<Integer,Unit>(...) { ... } | reflection.kt:116:40:116:44 | invoke | reflection.kt:116:40:116:44 | new (...) | . |
118+
| reflection.kt:126:9:126:13 | ...::... | reflection.kt:126:9:126:13 | new Function0<Unit>(...) { ... } | reflection.kt:126:9:126:13 | invoke | reflection.kt:126:9:126:13 | fn1(...) | ReflectionKt.fn1 |
117119
fieldAccessInsideInvocationMethods
118120
| reflection.kt:14:38:14:44 | ...::... | reflection.kt:14:38:14:44 | new Function1<C,Integer>(...) { ... } | reflection.kt:14:38:14:44 | invoke | reflection.kt:14:38:14:44 | this.<dispatchReceiver> |
119121
| reflection.kt:15:35:15:41 | ...::... | reflection.kt:15:35:15:41 | new KProperty0<Integer>(...) { ... } | reflection.kt:15:35:15:41 | get | reflection.kt:15:35:15:41 | this.<dispatchReceiver> |
@@ -225,3 +227,6 @@ modifiers
225227
| reflection.kt:109:17:109:27 | ...::... | reflection.kt:109:17:109:27 | set | public |
226228
| reflection.kt:116:40:116:44 | ...::... | reflection.kt:116:40:116:44 | invoke | override |
227229
| reflection.kt:116:40:116:44 | ...::... | reflection.kt:116:40:116:44 | invoke | public |
230+
| reflection.kt:126:9:126:13 | ...::... | reflection.kt:126:9:126:13 | invoke | public |
231+
compGenerated
232+
| reflection.kt:126:9:126:13 | | 1 |

java/ql/test/kotlin/library-tests/reflection/reflection.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,12 @@ class LocalFn {
116116
val x: KFunction1<Int, Unit> = ::fn1
117117
}
118118
}
119+
120+
121+
fun fn1() = 5
122+
123+
fun fn2(f: () -> Unit) = f()
124+
125+
fun adapted() {
126+
fn2(::fn1)
127+
}

java/ql/test/kotlin/library-tests/reflection/reflection.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,5 @@ query predicate modifiers(ClassInstanceExpr e, Method m, string modifier) {
8686
e.getAnonymousClass().getAMethod() = m and
8787
m.hasModifier(modifier)
8888
}
89+
90+
query predicate compGenerated(Element e, int i) { compiler_generated(e, i) }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.kt:1:1:1:20 | C1 | Unused class: C1 is not referenced within this codebase. If not used as an external API it should be removed. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Violations of Best Practice/Dead Code/DeadRefTypes.ql

0 commit comments

Comments
 (0)