Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,10 @@ open class KotlinFileExtractor(
logger.warnElement("Unrecognised class kind $kind", c)
}

if (c.origin == IrDeclarationOrigin.FILE_CLASS) {
tw.writeFile_class(id)
}

if (c.isData) {
tw.writeKtDataClasses(id)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fun a() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fun b() {
a()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class C {
fun c() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
| AKt.class:0:0:0:0 | AKt | true |
| B.kt:0:0:0:0 | BKt | true |
| C.kt:1:1:3:1 | C | false |
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import java

from Class c
where exists(c.getLocation().getFile().getRelativePath())
select c, any(boolean b | if c.isFileClass() then b = true else b = false)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from create_database_utils import *

runSuccessfully([get_cmd("kotlinc"), 'A.kt'])
run_codeql_database_create(['kotlinc -cp . B.kt C.kt'], lang="java")
4 changes: 4 additions & 0 deletions java/ql/lib/change-notes/2023-07-11-file-classes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: feature
---
* A `Class.isFileClass()` predicate, to identify Kotlin file classes, has been added.
6 changes: 6 additions & 0 deletions java/ql/lib/semmle/code/java/Type.qll
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,12 @@ class Class extends ClassOrInterface {
)
}

/**
* Holds if this class is a Kotlin "file class", e.g. the class FooKt
* for top-level entities in Foo.kt.
*/
predicate isFileClass() { file_class(this) }

override string getAPrimaryQlClass() { result = "Class" }
}

Expand Down
2 changes: 2 additions & 0 deletions java/ql/test/library-tests/file_classes/A.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fun a() {
}
3 changes: 3 additions & 0 deletions java/ql/test/library-tests/file_classes/B.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fun b() {
a()
}
3 changes: 3 additions & 0 deletions java/ql/test/library-tests/file_classes/C.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class C {
fun c() {}
}
3 changes: 3 additions & 0 deletions java/ql/test/library-tests/file_classes/classes.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
| A.kt:0:0:0:0 | AKt | true |
| B.kt:0:0:0:0 | BKt | true |
| C.kt:1:1:3:1 | C | false |
5 changes: 5 additions & 0 deletions java/ql/test/library-tests/file_classes/classes.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import java

from Class c
where c.fromSource()
select c, any(boolean b | if c.isFileClass() then b = true else b = false)