Skip to content

Commit b5fbab8

Browse files
authored
Merge pull request github#80 from github/igfoo/more
Kotlin: Extract type aliases
2 parents 8d510be + 347bb3b commit b5fbab8

File tree

8 files changed

+97
-12
lines changed

8 files changed

+97
-12
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,10 @@ open class KotlinUsesExtractor(
411411
}
412412

413413
fun useSimpleType(s: IrSimpleType, canReturnPrimitiveTypes: Boolean): TypeResults {
414+
if (s.abbreviation != null) {
415+
// TODO: Extract this information
416+
logger.warn(Severity.ErrorSevere, "Type alias ignored for " + s.render())
417+
}
414418
// We use this when we don't actually have an IrClass for a class
415419
// we want to refer to
416420
fun makeClass(pkgName: String, className: String): Label<DbClass> {
@@ -765,6 +769,18 @@ class X {
765769
return id
766770
}
767771

772+
private fun getTypeAliasLabel(ta: IrTypeAlias) : String {
773+
val parentId = useDeclarationParent(ta.parent)
774+
val label = "@\"type_alias;{$parentId};${ta.name.asString()}\""
775+
return label
776+
}
777+
778+
fun useTypeAlias(ta: IrTypeAlias): Label<out DbKt_type_alias> {
779+
var label = getTypeAliasLabel(ta)
780+
val id: Label<DbKt_type_alias> = tw.getLabelFor(label)
781+
return id
782+
}
783+
768784
fun useVariable(v: IrVariable): Label<out DbLocalvar> {
769785
return tw.getVariableLabelFor<DbLocalvar>(v)
770786
}
@@ -789,6 +805,7 @@ open class KotlinFileExtractor(
789805
}
790806
is IrProperty -> extractProperty(declaration, parentId)
791807
is IrEnumEntry -> extractEnumEntry(declaration, parentId)
808+
is IrTypeAlias -> extractTypeAlias(declaration) // TODO: Pass in and use parentId
792809
else -> logger.warnElement(Severity.ErrorSevere, "Unrecognised IrDeclaration: " + declaration.javaClass, declaration)
793810
}
794811
}
@@ -1027,6 +1044,19 @@ open class KotlinFileExtractor(
10271044
}
10281045
}
10291046

1047+
fun extractTypeAlias(ta: IrTypeAlias) {
1048+
if (ta.typeParameters.isNotEmpty()) {
1049+
// TODO: Extract this information
1050+
logger.warn(Severity.ErrorSevere, "Type alias type parameters ignored for " + ta.render())
1051+
}
1052+
val id = useTypeAlias(ta)
1053+
val locId = tw.getLocation(ta)
1054+
// TODO: We don't really want to generate any Java types here; we only want the KT type:
1055+
val type = useType(ta.expandedType)
1056+
tw.writeKt_type_alias(id, ta.name.asString(), type.kotlinResult.id)
1057+
tw.writeHasLocation(id, locId)
1058+
}
1059+
10301060
fun extractBody(b: IrBody, callable: Label<out DbCallable>) {
10311061
when(b) {
10321062
is IrBlockBody -> extractBlockBody(b, callable, callable, 0)

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

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ open class Logger(val logCounter: LogCounter, open val tw: TrapWriter) {
3333
return "[${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())} K]"
3434
}
3535

36+
private fun getWarningLocation(): String? {
37+
val st = Exception().stackTrace
38+
for(x in st) {
39+
when(x.className) {
40+
"com.github.codeql.Logger",
41+
"com.github.codeql.FileLogger" -> {}
42+
else -> {
43+
return x.toString()
44+
}
45+
}
46+
}
47+
return null
48+
}
49+
3650
fun flush() {
3751
tw.flush()
3852
System.out.flush()
@@ -53,26 +67,26 @@ open class Logger(val logCounter: LogCounter, open val tw: TrapWriter) {
5367
fun trace(msg: String, exn: Exception) {
5468
trace(msg + " // " + exn)
5569
}
56-
fun warn(severity: Severity, msg: String, locationString: String? = null, locationId: Label<DbLocation> = tw.unknownLocation, stackIndex: Int = 2) {
57-
val st = Exception().stackTrace
70+
fun warn(severity: Severity, msg: String, locationString: String? = null, locationId: Label<DbLocation> = tw.unknownLocation) {
71+
val warningLoc = getWarningLocation()
72+
val warningLocStr = if(warningLoc == null) "<unknown location>" else warningLoc
5873
val suffix =
59-
if(st.size < stackIndex + 1) {
74+
if(warningLoc == null) {
6075
" Missing caller information.\n"
6176
} else {
62-
val caller = st[stackIndex].toString()
63-
val count = logCounter.warningCounts.getOrDefault(caller, 0) + 1
64-
logCounter.warningCounts[caller] = count
77+
val count = logCounter.warningCounts.getOrDefault(warningLoc, 0) + 1
78+
logCounter.warningCounts[warningLoc] = count
6579
when {
6680
logCounter.warningLimit <= 0 -> ""
67-
count == logCounter.warningLimit -> " Limit reached for warnings from $caller.\n"
81+
count == logCounter.warningLimit -> " Limit reached for warnings from $warningLoc.\n"
6882
count > logCounter.warningLimit -> return
6983
else -> ""
7084
}
7185
}
7286
val ts = timestamp()
7387
tw.writeDiagnostics(StarLabel(), severity.sev, "", msg, "$ts $msg\n$suffix", locationId)
7488
val locStr = if (locationString == null) "" else "At " + locationString + ": "
75-
print("$ts Warning: $locStr$msg\n$suffix")
89+
print("$ts Warning($warningLocStr): $locStr$msg\n$suffix")
7690
}
7791
fun warn(msg: String, exn: Exception) {
7892
warn(Severity.Warn, msg + " // " + exn)
@@ -102,9 +116,9 @@ class FileLogger(logCounter: LogCounter, override val tw: FileTrapWriter): Logge
102116
return "[${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())} K]"
103117
}
104118

105-
fun warnElement(severity: Severity, msg: String, element: IrElement, stackIndex: Int = 3) {
119+
fun warnElement(severity: Severity, msg: String, element: IrElement) {
106120
val locationString = tw.getLocationString(element)
107121
val locationId = tw.getLocation(element)
108-
warn(severity, msg, locationString, locationId, stackIndex)
122+
warn(severity, msg, locationString, locationId)
109123
}
110124
}

java/ql/lib/config/semmlecode.dbscheme

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,12 @@ kt_notnull_types(
324324
int classid: @classorinterface ref
325325
)
326326

327+
kt_type_alias(
328+
unique int id: @kt_type_alias,
329+
string name: string ref,
330+
int kttypeid: @kt_type ref
331+
)
332+
327333
@kt_type = @kt_nullable_type | @kt_notnull_type
328334

329335
isRecord(
@@ -926,19 +932,22 @@ javadocText(
926932
@classorarray = @class | @array;
927933
@type = @primitive | @reftype;
928934
@callable = @method | @constructor;
935+
936+
/** A program element that has a name. */
929937
@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field |
930-
@annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type;
938+
@annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias;
931939

932940
@modifiable = @member_modifiable| @param | @localvar ;
933941

934942
@member_modifiable = @class | @interface | @method | @constructor | @field ;
935943

936944
@member = @method | @constructor | @field | @reftype ;
937945

946+
/** A program element that has a location. */
938947
@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception
939948
| @boundedtype | @typebound | @array | @primitive
940949
| @import | @stmt | @expr | @whenbranch | @localvar | @javadoc | @javadocTag | @javadocText
941-
| @xmllocatable | @ktcomment;
950+
| @xmllocatable | @ktcomment | @kt_type_alias;
942951

943952
@top = @element | @locatable | @folder;
944953

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ predicate hasName(Element e, string name) {
4343
arrays(e, name, _, _, _, _, _)
4444
or
4545
modifiers(e, name)
46+
or
47+
kt_type_alias(e, name, _)
4648
}
4749

4850
/**

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,10 @@ class KotlinNotnullType extends KotlinType, @kt_notnull_type {
2525
override string getAPrimaryQlClass() { result = "KotlinNotnullType" }
2626
}
2727

28+
class KotlinTypeAlias extends Element, @kt_type_alias {
29+
override string getAPrimaryQlClass() { result = "KotlinTypeAlias" }
30+
31+
KotlinType getKotlinType() {
32+
kt_type_alias(this, _, result)
33+
}
34+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
class MyClass<T> {}
3+
4+
typealias AliasInt = Int
5+
typealias AliasX = MyClass<Int>
6+
typealias AliasY = MyClass<AliasInt>
7+
8+
fun someFun(
9+
x1: Int,
10+
x2: AliasInt,
11+
x3: MyClass<Int>,
12+
x4: AliasX,
13+
x5: MyClass<AliasInt>,
14+
x6: AliasY) {
15+
}
16+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| test.kt:4:1:4:24 | AliasInt | file://:0:0:0:0 | Kotlin not-null Int |
2+
| test.kt:5:1:5:31 | AliasX | file://:0:0:0:0 | Kotlin not-null MyClass |
3+
| test.kt:6:1:6:36 | AliasY | file://:0:0:0:0 | Kotlin not-null MyClass |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import java
2+
3+
from KotlinTypeAlias ta
4+
select ta, ta.getKotlinType()

0 commit comments

Comments
 (0)