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

Skip to content

Commit 85e713f

Browse files
tamasvajkigfoo
authored andcommitted
Extract generic type parameters as reference types even for primitive Kotlin types + add simplified array extraction
1 parent b542769 commit 85e713f

5 files changed

Lines changed: 72 additions & 70 deletions

File tree

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

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
1515
import org.jetbrains.kotlin.ir.types.*
1616
import org.jetbrains.kotlin.ir.util.dumpKotlinLike
1717
import org.jetbrains.kotlin.ir.util.packageFqName
18+
import org.jetbrains.kotlin.ir.util.parentAsClass
1819
import org.jetbrains.kotlin.ir.util.render
1920
import java.io.File
2021
import java.io.FileOutputStream
@@ -170,7 +171,7 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
170171
val pkg = file.fqName.asString()
171172
val pkgId = extractPackage(pkg)
172173
tw.writeCupackage(id, pkgId)
173-
file.declarations.map { extractDeclaration(it, Optional.empty()) }
174+
file.declarations.map { extractDeclaration(it) }
174175
CommentExtractor(this).extract()
175176
}
176177

@@ -218,25 +219,33 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
218219
return id
219220
}
220221

221-
fun extractDeclaration(declaration: IrDeclaration, optParentid: Optional<Label<out DbReftype>>) {
222+
fun extractDeclaration(declaration: IrDeclaration) {
222223
when (declaration) {
223224
is IrClass -> useClass(declaration, listOf())
224-
is IrFunction -> extractFunction(declaration, if (optParentid.isPresent()) optParentid.get() else fileClass)
225+
is IrFunction -> extractFunction(declaration)
225226
is IrAnonymousInitializer -> {
226227
// Leaving this intentionally empty. init blocks are extracted during class extraction.
227228
}
228-
is IrProperty -> extractProperty(declaration, if (optParentid.isPresent()) optParentid.get() else fileClass)
229+
is IrProperty -> extractProperty(declaration)
229230
else -> logger.warnElement(Severity.ErrorSevere, "Unrecognised IrDeclaration: " + declaration.javaClass, declaration)
230231
}
231232
}
232233

233-
fun useSimpleType(s: IrSimpleType): Label<out DbType> {
234+
fun useSimpleType(s: IrSimpleType, canReturnPrimitiveTypes: Boolean): Label<out DbType> {
234235
fun primitiveType(name: String): Label<DbPrimitive> {
235236
return tw.getLabelFor("@\"type;$name\"", {
236237
tw.writePrimitives(it, name)
237238
})
238239
}
239240
when {
241+
// temporary fix for type parameters types that would otherwise be primitive types
242+
!canReturnPrimitiveTypes && (s.isPrimitiveType() || s.isUnsignedType() || s.isString()) -> {
243+
val classifier: IrClassifierSymbol = s.classifier
244+
val cls: IrClass = classifier.owner as IrClass
245+
246+
return useClass(cls, s.arguments)
247+
}
248+
240249
s.isByte() -> return primitiveType("byte")
241250
s.isShort() -> return primitiveType("short")
242251
s.isInt() -> return primitiveType("int")
@@ -254,10 +263,18 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
254263
s.isChar() -> return primitiveType("char")
255264
s.isString() -> return primitiveType("string") // TODO: Wrong
256265

257-
s.isNullable() && s.hasQuestionMark -> return useType(s.makeNotNull()) // TODO: Wrong
266+
s.isNullable() && s.hasQuestionMark -> return useType(s.makeNotNull(), canReturnPrimitiveTypes) // TODO: Wrong
258267

259268
s.isNothing() -> return primitiveType("<nulltype>")
260269

270+
s.isArray() && s.arguments.isNotEmpty() -> {
271+
// todo: fix this, this is only a dummy implementation to let the tests pass
272+
val elementType = useType(s.getArrayElementType(pluginContext.irBuiltIns))
273+
val id = tw.getLabelFor<DbArray>("@\"array;1;{$elementType}\"")
274+
tw.writeArrays(id, "ARRAY", elementType, 1, elementType)
275+
return id
276+
}
277+
261278
s.classifier.owner is IrClass -> {
262279
val classifier: IrClassifierSymbol = s.classifier
263280
val cls: IrClass = classifier.owner as IrClass
@@ -303,22 +320,29 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
303320
}
304321

305322
fun useTypeParameter(param: IrTypeParameter): Label<out DbTypevariable> {
306-
return tw.getLabelFor(getTypeParameterLabel(param))
323+
val l = getTypeParameterLabel(param)
324+
return tw.getExistingLabelFor(l) ?: extractTypeParameter(param)
307325
}
308326

309-
private fun extractTypeParameter(tp: IrTypeParameter, optParentid: Optional<Label<out DbTypeorcallable>>) {
310-
val id = useTypeParameter(tp)
327+
private fun extractTypeParameter(tp: IrTypeParameter): Label<out DbTypevariable> {
328+
val id = tw.getLabelFor<DbTypevariable>(getTypeParameterLabel(tp))
311329

312-
if (!optParentid.isPresent) {
313-
logger.warnElement(Severity.ErrorSevere, "Couldn't find expected parent of type parameter.", tp)
314-
return
330+
val parentId: Label<out DbTypeorcallable> = when (val parent = tp.parent) {
331+
is IrFunction -> useFunction(parent)
332+
is IrClass -> useClass(parent, listOf())
333+
else -> {
334+
logger.warnElement(Severity.ErrorSevere, "Unexpected type parameter parent", tp)
335+
fakeLabel()
336+
}
315337
}
316338

317-
tw.writeTypeVars(id, tp.name.asString(), tp.index, 0, optParentid.get())
339+
tw.writeTypeVars(id, tp.name.asString(), tp.index, 0, parentId)
318340
val locId = tw.getLocation(tp)
319341
tw.writeHasLocation(id, locId)
320342

321343
// todo: add type bounds
344+
345+
return id
322346
}
323347

324348
private fun getClassLabel(c: IrClass, typeArgs: List<IrTypeArgument>): String {
@@ -351,7 +375,7 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
351375
return wildcardId
352376
}
353377
is IrTypeProjection -> {
354-
return useType(arg.type) as Label<out DbReftype>
378+
return useType(arg.type, false) as Label<out DbReftype>
355379
}
356380
else -> {
357381
logger.warnElement(Severity.ErrorSevere, "Unexpected type argument.", reportOn)
@@ -441,19 +465,19 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
441465
val unbound = useClass(c, listOf())
442466
tw.writeErasure(id, unbound)
443467
} else {
444-
c.typeParameters.map { extractTypeParameter(it, Optional.of(id)) }
468+
c.typeParameters.map { extractTypeParameter(it) }
445469

446-
c.declarations.map { extractDeclaration(it, Optional.of(id)) }
470+
c.declarations.map { extractDeclaration(it) }
447471

448472
extractObjectInitializerFunction(c, id)
449473
}
450474

451475
return id
452476
}
453477

454-
fun useType(t: IrType): Label<out DbType> {
478+
fun useType(t: IrType, canReturnPrimitiveTypes: Boolean = true): Label<out DbType> {
455479
when(t) {
456-
is IrSimpleType -> return useSimpleType(t)
480+
is IrSimpleType -> return useSimpleType(t, canReturnPrimitiveTypes)
457481
is IrClass -> return useClass(t, listOf())
458482
else -> {
459483
logger.warn(Severity.ErrorSevere, "Unrecognised IrType: " + t.javaClass)
@@ -482,6 +506,13 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
482506
return erase(owner.superTypes.get(0))
483507
}
484508

509+
// todo: fix this:
510+
if (t.makeNotNull().isArray()) {
511+
val elementType = t.getArrayElementType(pluginContext.irBuiltIns)
512+
val erasedElementType = erase(elementType)
513+
return (classifier as IrClassSymbol).typeWith(erasedElementType)
514+
}
515+
485516
if (owner is IrClass) {
486517
return (classifier as IrClassSymbol).typeWith()
487518
}
@@ -616,20 +647,22 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
616647
}
617648
}
618649

619-
fun extractFunction(f: IrFunction, parentid: Label<out DbReftype>) {
650+
fun extractFunction(f: IrFunction) {
620651
currentFunction = f
621652

622653
val locId = tw.getLocation(f)
623654
val signature = "TODO"
624655
val returnTypeId = useType(f.returnType)
625656

657+
val parentId = if (f.parent is IrClass ) useClass(f.parent as IrClass, listOf()) else fileClass
658+
626659
val id: Label<out DbCallable>
627660
if (f.symbol is IrConstructorSymbol) {
628661
id = useFunction<DbConstructor>(f)
629-
tw.writeConstrs(id, f.returnType.classFqName?.shortName()?.asString() ?: f.name.asString(), signature, returnTypeId, parentid, id)
662+
tw.writeConstrs(id, f.returnType.classFqName?.shortName()?.asString() ?: f.name.asString(), signature, returnTypeId, parentId, id)
630663
} else {
631664
id = useFunction<DbMethod>(f)
632-
tw.writeMethods(id, f.name.asString(), signature, returnTypeId, parentid, id)
665+
tw.writeMethods(id, f.name.asString(), signature, returnTypeId, parentId, id)
633666

634667
val extReceiver = f.extensionReceiverParameter
635668
if (extReceiver != null) {
@@ -647,7 +680,7 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
647680
extractValueParameter(vp, id, i)
648681
}
649682

650-
f.typeParameters.map { extractTypeParameter(it, Optional.of(id)) }
683+
f.typeParameters.map { extractTypeParameter(it) }
651684

652685
currentFunction = null
653686
}
@@ -664,15 +697,16 @@ class KotlinFileExtractor(val logger: FileLogger, val tw: FileTrapWriter, val fi
664697
return id
665698
}
666699

667-
fun extractProperty(p: IrProperty, parentid: Label<out DbReftype>) {
700+
fun extractProperty(p: IrProperty) {
668701
val bf = p.backingField
669702
if(bf == null) {
670703
logger.warnElement(Severity.ErrorSevere, "IrProperty without backing field", p)
671704
} else {
672705
val id = useProperty(p)
673706
val locId = tw.getLocation(p)
674707
val typeId = useType(bf.type)
675-
tw.writeFields(id, p.name.asString(), typeId, parentid, id)
708+
val parentId = if (p.parent is IrClass ) useClass(p.parent as IrClass, listOf()) else fileClass
709+
tw.writeFields(id, p.name.asString(), typeId, parentId, id)
676710
tw.writeHasLocation(id, locId)
677711
}
678712
}

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

Lines changed: 0 additions & 5 deletions
This file was deleted.

java/ql/test/kotlin/library-tests/generics/DB-CHECK.expected

Lines changed: 0 additions & 31 deletions
This file was deleted.

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ genericType
44
| generics.kt:13:1:18:1 | C1 | generics.kt:13:13:13:13 | W | 1 |
55
parameterizedType
66
| generics.kt:11:1:11:19 | C0 | generics.kt:11:1:11:19 | C0 | 0 | file://:0:0:0:0 | * |
7-
| generics.kt:11:1:11:19 | C0 | generics.kt:11:1:11:19 | C0 | 0 | file://:0:0:0:0 | int |
7+
| generics.kt:11:1:11:19 | C0 | generics.kt:11:1:11:19 | C0 | 0 | file://:0:0:0:0 | Int |
88
| generics.kt:11:1:11:19 | C0 | generics.kt:11:1:11:19 | C0 | 0 | generics.kt:7:6:7:6 | S |
99
| generics.kt:11:1:11:19 | C0 | generics.kt:11:1:11:19 | C0 | 0 | generics.kt:11:15:11:15 | V |
1010
| generics.kt:11:1:11:19 | C0 | generics.kt:11:1:11:19 | C0 | 0 | generics.kt:13:13:13:13 | W |
11-
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 0 | file://:0:0:0:0 | int |
12-
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 0 | file://:0:0:0:0 | string |
13-
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 0 | file://:0:0:0:0 | string |
11+
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 0 | file://:0:0:0:0 | Int |
12+
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 0 | file://:0:0:0:0 | String |
13+
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 0 | file://:0:0:0:0 | String |
1414
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 0 | generics.kt:13:10:13:10 | T |
1515
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 0 | generics.kt:15:10:15:10 | U |
16-
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 1 | file://:0:0:0:0 | int |
17-
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 1 | file://:0:0:0:0 | int |
18-
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 1 | file://:0:0:0:0 | string |
16+
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 1 | file://:0:0:0:0 | Int |
17+
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 1 | file://:0:0:0:0 | Int |
18+
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 1 | file://:0:0:0:0 | String |
1919
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 1 | generics.kt:13:13:13:13 | W |
2020
| generics.kt:13:1:18:1 | C1 | generics.kt:13:1:18:1 | C1 | 1 | generics.kt:15:10:15:10 | U |
2121
genericFunction

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import java
22

3-
query predicate genericType(GenericType t, TypeVariable tv, int i) { t.getTypeParameter(i) = tv }
3+
query predicate genericType(GenericType t, TypeVariable tv, int i) {
4+
t.getTypeParameter(i) = tv and t.getFile().getExtension() = "kt"
5+
}
46

57
query predicate parameterizedType(ParameterizedType t, GenericType gt, int i, RefType ta) {
68
t.getGenericType() = gt and
7-
t.getTypeArgument(i) = ta
9+
t.getTypeArgument(i) = ta and
10+
t.getFile().getExtension() = "kt"
811
}
912

1013
query predicate genericFunction(GenericCallable c, TypeVariable tv, int i) {
11-
c.getTypeParameter(i) = tv
14+
c.getTypeParameter(i) = tv and
15+
c.getFile().getExtension() = "kt"
1216
}
1317

1418
query predicate genericCall(GenericCall c, TypeVariable tv, Type t) { c.getATypeArgument(tv) = t }

0 commit comments

Comments
 (0)