Skip to content

Commit 92b8c0f

Browse files
authored
Merge pull request #9563 from smowton/smowton/fix/name-trap-files-after-jvmnames
Kotlin: Name trap files after jvmnames
2 parents 5923eb4 + 90e8d4e commit 92b8c0f

File tree

6 files changed

+105
-77
lines changed

6 files changed

+105
-77
lines changed

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

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -66,80 +66,6 @@ open class KotlinUsesExtractor(
6666
TypeResult(fakeKotlinType(), "", "")
6767
)
6868

69-
private data class MethodKey(val className: FqName, val functionName: Name)
70-
71-
private fun makeDescription(className: FqName, functionName: String) = MethodKey(className, Name.guessByFirstCharacter(functionName))
72-
73-
// This essentially mirrors SpecialBridgeMethods.kt, a backend pass which isn't easily available to our extractor.
74-
private val specialFunctions = mapOf(
75-
makeDescription(StandardNames.FqNames.collection, "<get-size>") to "size",
76-
makeDescription(FqName("java.util.Collection"), "<get-size>") to "size",
77-
makeDescription(StandardNames.FqNames.map, "<get-size>") to "size",
78-
makeDescription(FqName("java.util.Map"), "<get-size>") to "size",
79-
makeDescription(StandardNames.FqNames.charSequence.toSafe(), "<get-length>") to "length",
80-
makeDescription(FqName("java.lang.CharSequence"), "<get-length>") to "length",
81-
makeDescription(StandardNames.FqNames.map, "<get-keys>") to "keySet",
82-
makeDescription(FqName("java.util.Map"), "<get-keys>") to "keySet",
83-
makeDescription(StandardNames.FqNames.map, "<get-values>") to "values",
84-
makeDescription(FqName("java.util.Map"), "<get-values>") to "values",
85-
makeDescription(StandardNames.FqNames.map, "<get-entries>") to "entrySet",
86-
makeDescription(FqName("java.util.Map"), "<get-entries>") to "entrySet",
87-
makeDescription(StandardNames.FqNames.mutableList, "removeAt") to "remove",
88-
makeDescription(FqName("java.util.List"), "removeAt") to "remove",
89-
makeDescription(StandardNames.FqNames._enum.toSafe(), "<get-ordinal>") to "ordinal",
90-
makeDescription(FqName("java.lang.Enum"), "<get-ordinal>") to "ordinal",
91-
makeDescription(StandardNames.FqNames._enum.toSafe(), "<get-name>") to "name",
92-
makeDescription(FqName("java.lang.Enum"), "<get-name>") to "name",
93-
makeDescription(StandardNames.FqNames.number.toSafe(), "toByte") to "byteValue",
94-
makeDescription(FqName("java.lang.Number"), "toByte") to "byteValue",
95-
makeDescription(StandardNames.FqNames.number.toSafe(), "toShort") to "shortValue",
96-
makeDescription(FqName("java.lang.Number"), "toShort") to "shortValue",
97-
makeDescription(StandardNames.FqNames.number.toSafe(), "toInt") to "intValue",
98-
makeDescription(FqName("java.lang.Number"), "toInt") to "intValue",
99-
makeDescription(StandardNames.FqNames.number.toSafe(), "toLong") to "longValue",
100-
makeDescription(FqName("java.lang.Number"), "toLong") to "longValue",
101-
makeDescription(StandardNames.FqNames.number.toSafe(), "toFloat") to "floatValue",
102-
makeDescription(FqName("java.lang.Number"), "toFloat") to "floatValue",
103-
makeDescription(StandardNames.FqNames.number.toSafe(), "toDouble") to "doubleValue",
104-
makeDescription(FqName("java.lang.Number"), "toDouble") to "doubleValue",
105-
)
106-
107-
private val specialFunctionShortNames = specialFunctions.keys.map { it.functionName }.toSet()
108-
109-
fun getSpecialJvmName(f: IrFunction): String? {
110-
if (specialFunctionShortNames.contains(f.name) && f is IrSimpleFunction) {
111-
f.allOverridden(true).forEach { overriddenFunc ->
112-
overriddenFunc.parentClassOrNull?.fqNameWhenAvailable?.let { parentFqName ->
113-
specialFunctions[MethodKey(parentFqName, f.name)]?.let {
114-
return it
115-
}
116-
}
117-
}
118-
}
119-
return null
120-
}
121-
122-
fun getJvmName(container: IrAnnotationContainer): String? {
123-
for(a: IrConstructorCall in container.annotations) {
124-
val t = a.type
125-
if (t is IrSimpleType && a.valueArgumentsCount == 1) {
126-
val owner = t.classifier.owner
127-
val v = a.getValueArgument(0)
128-
if (owner is IrClass) {
129-
val aPkg = owner.packageFqName?.asString()
130-
val name = owner.name.asString()
131-
if(aPkg == "kotlin.jvm" && name == "JvmName" && v is IrConst<*>) {
132-
val value = v.value
133-
if (value is String) {
134-
return value
135-
}
136-
}
137-
}
138-
}
139-
}
140-
return (container as? IrFunction)?.let { getSpecialJvmName(container) }
141-
}
142-
14369
@OptIn(kotlin.ExperimentalStdlibApi::class) // Annotation required by kotlin versions < 1.5
14470
fun extractFileClass(f: IrFile): Label<out DbClass> {
14571
val fileName = f.fileEntry.name

java/kotlin-extractor/src/main/kotlin/utils/ClassNames.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.codeql
22

3+
import com.github.codeql.utils.getJvmName
34
import com.intellij.openapi.vfs.StandardFileSystems
45
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
56
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
@@ -18,17 +19,19 @@ import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
1819
// and declarations within them into the parent class' JLS 13.1 name as
1920
// specified above, followed by a `$` separator and then the short name
2021
// for `that`.
22+
private fun getName(d: IrDeclarationWithName) = (d as? IrAnnotationContainer)?.let { getJvmName(it) } ?: d.name.asString()
23+
2124
fun getIrDeclBinaryName(that: IrDeclaration): String {
2225
val shortName = when(that) {
23-
is IrDeclarationWithName -> that.name.asString()
26+
is IrDeclarationWithName -> getName(that)
2427
else -> "(unknown-name)"
2528
}
2629
val internalName = StringBuilder(shortName);
2730
generateSequence(that.parent) { (it as? IrDeclaration)?.parent }
2831
.forEach {
2932
when (it) {
30-
is IrClass -> internalName.insert(0, it.name.asString() + "$")
31-
is IrPackageFragment -> it.fqName.asString().takeIf { it.isNotEmpty() }?.let { internalName.insert(0, "$it.") }
33+
is IrClass -> internalName.insert(0, getName(it) + "$")
34+
is IrPackageFragment -> it.fqName.asString().takeIf { fqName -> fqName.isNotEmpty() }?.let { fqName -> internalName.insert(0, "$fqName.") }
3235
}
3336
}
3437
return internalName.toString()
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.github.codeql.utils
2+
3+
import org.jetbrains.kotlin.backend.common.ir.allOverridden
4+
import org.jetbrains.kotlin.builtins.StandardNames
5+
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
6+
import org.jetbrains.kotlin.ir.declarations.IrClass
7+
import org.jetbrains.kotlin.ir.declarations.IrFunction
8+
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
9+
import org.jetbrains.kotlin.ir.expressions.IrConst
10+
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
11+
import org.jetbrains.kotlin.ir.types.IrSimpleType
12+
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
13+
import org.jetbrains.kotlin.ir.util.packageFqName
14+
import org.jetbrains.kotlin.ir.util.parentClassOrNull
15+
import org.jetbrains.kotlin.name.FqName
16+
import org.jetbrains.kotlin.name.Name
17+
18+
private data class MethodKey(val className: FqName, val functionName: Name)
19+
20+
private fun makeDescription(className: FqName, functionName: String) = MethodKey(className, Name.guessByFirstCharacter(functionName))
21+
22+
// This essentially mirrors SpecialBridgeMethods.kt, a backend pass which isn't easily available to our extractor.
23+
private val specialFunctions = mapOf(
24+
makeDescription(StandardNames.FqNames.collection, "<get-size>") to "size",
25+
makeDescription(FqName("java.util.Collection"), "<get-size>") to "size",
26+
makeDescription(StandardNames.FqNames.map, "<get-size>") to "size",
27+
makeDescription(FqName("java.util.Map"), "<get-size>") to "size",
28+
makeDescription(StandardNames.FqNames.charSequence.toSafe(), "<get-length>") to "length",
29+
makeDescription(FqName("java.lang.CharSequence"), "<get-length>") to "length",
30+
makeDescription(StandardNames.FqNames.map, "<get-keys>") to "keySet",
31+
makeDescription(FqName("java.util.Map"), "<get-keys>") to "keySet",
32+
makeDescription(StandardNames.FqNames.map, "<get-values>") to "values",
33+
makeDescription(FqName("java.util.Map"), "<get-values>") to "values",
34+
makeDescription(StandardNames.FqNames.map, "<get-entries>") to "entrySet",
35+
makeDescription(FqName("java.util.Map"), "<get-entries>") to "entrySet",
36+
makeDescription(StandardNames.FqNames.mutableList, "removeAt") to "remove",
37+
makeDescription(FqName("java.util.List"), "removeAt") to "remove",
38+
makeDescription(StandardNames.FqNames._enum.toSafe(), "<get-ordinal>") to "ordinal",
39+
makeDescription(FqName("java.lang.Enum"), "<get-ordinal>") to "ordinal",
40+
makeDescription(StandardNames.FqNames._enum.toSafe(), "<get-name>") to "name",
41+
makeDescription(FqName("java.lang.Enum"), "<get-name>") to "name",
42+
makeDescription(StandardNames.FqNames.number.toSafe(), "toByte") to "byteValue",
43+
makeDescription(FqName("java.lang.Number"), "toByte") to "byteValue",
44+
makeDescription(StandardNames.FqNames.number.toSafe(), "toShort") to "shortValue",
45+
makeDescription(FqName("java.lang.Number"), "toShort") to "shortValue",
46+
makeDescription(StandardNames.FqNames.number.toSafe(), "toInt") to "intValue",
47+
makeDescription(FqName("java.lang.Number"), "toInt") to "intValue",
48+
makeDescription(StandardNames.FqNames.number.toSafe(), "toLong") to "longValue",
49+
makeDescription(FqName("java.lang.Number"), "toLong") to "longValue",
50+
makeDescription(StandardNames.FqNames.number.toSafe(), "toFloat") to "floatValue",
51+
makeDescription(FqName("java.lang.Number"), "toFloat") to "floatValue",
52+
makeDescription(StandardNames.FqNames.number.toSafe(), "toDouble") to "doubleValue",
53+
makeDescription(FqName("java.lang.Number"), "toDouble") to "doubleValue",
54+
)
55+
56+
private val specialFunctionShortNames = specialFunctions.keys.map { it.functionName }.toSet()
57+
58+
fun getSpecialJvmName(f: IrFunction): String? {
59+
if (specialFunctionShortNames.contains(f.name) && f is IrSimpleFunction) {
60+
f.allOverridden(true).forEach { overriddenFunc ->
61+
overriddenFunc.parentClassOrNull?.fqNameWhenAvailable?.let { parentFqName ->
62+
specialFunctions[MethodKey(parentFqName, f.name)]?.let {
63+
return it
64+
}
65+
}
66+
}
67+
}
68+
return null
69+
}
70+
71+
fun getJvmName(container: IrAnnotationContainer): String? {
72+
for(a: IrConstructorCall in container.annotations) {
73+
val t = a.type
74+
if (t is IrSimpleType && a.valueArgumentsCount == 1) {
75+
val owner = t.classifier.owner
76+
val v = a.getValueArgument(0)
77+
if (owner is IrClass) {
78+
val aPkg = owner.packageFqName?.asString()
79+
val name = owner.name.asString()
80+
if(aPkg == "kotlin.jvm" && name == "JvmName" && v is IrConst<*>) {
81+
val value = v.value
82+
if (value is String) {
83+
return value
84+
}
85+
}
86+
}
87+
}
88+
}
89+
return (container as? IrFunction)?.let { getSpecialJvmName(container) }
90+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.kt:1:100:1:109 | mutableIterator(...) | mutableIterator |
2+
| test.kt:3:73:3:82 | iterator(...) | iterator |
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fun getIter(m: MutableMap<String, Int>): MutableIterator<MutableMap.MutableEntry<String, Int>> = m.iterator()
2+
3+
fun getIter2(m: Map<String, Int>): Iterator<Map.Entry<String, Int>> = m.iterator()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import java
2+
3+
from MethodAccess ma
4+
select ma, ma.getCallee().toString()

0 commit comments

Comments
 (0)