How to get declaring KtFile/KtClass using KtCallExpression? - kotlin

I'm using kotlin compiler to analyze kotlin source file and I need to get where the method is defined using KtCallExpression.
KtCallExpression in question is retrieved from method call.
For better explanation, here's example, if there's source file named Main.kt with contents:
fun main() {
f1()
Test.f2()
}
fun f1() {
}
class Test {
companion object {
fun f2() {
}
}
}
when analyzing function main, it will produce 2 KtCallExpression, one for f1() and other for f2()
However I'm not sure how to get file Main.kt from KtCallExpression for f1(), or class Test from KtCallExpression for f2()
I tried to look for its documentations, however Kotlin compiler doesn't contain enough docs. I've also tried bunch of auto completion suggested by Intellij Idea but none of those doesn't seem to lead me to original declaration.

Related

When I use the generic method in Route then I am getting compiler Backend Internal error: Exception during IR lowering in Ktor

I am trying to create a dynamic service based on the data class model defined by user and they registerDataModels() method appDataModule() it should automatically create all based method in the router service. When I try to achive using generics in those method I am getting a compiler error. Is there any other better way to dynamically create route methods like by defining the datamodel by developer and then service should be automatically created?
org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering
File being compiled: */api/AppConfigService.kt
The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:47)
File is unknown
The root cause java.lang.AssertionError was thrown at: org.jetbrains.kotlin.codegen.coroutines.CoroutineTransformerMethodVisitor.spillVariables(CoroutineTransformerMethodVisitor.kt:636)
fun Application.registerDataModels() {
appDataModule<M1>()
appDataModule<M2>()
appDataModule<M3>()
}
inline fun <reified T: DBModel> Application.appDataModule() {
routing {
createAppData<T>()
updateAppData<T>()
deleteAppData<T>()
}
}
inline fun <reified T: DBModel> Route.createAppData() {
put("/api/data/${getName<T>()}/create") {
authenticated {
create<T>{}
}
}
}
inline fun <reified T: DBModel> Route.updateAppData() {
put("/api/data/${getName<T>()}/update") {
authenticated {
update<T>{}
}
}
}
inline fun <reified T: DBModel> Route.deleteAppData() {
put("/api/data/${getName<T>()}/delete") {
authenticated {
delete<T>{}
}
}
}
Note: This answer assumed that code would be loaded at runtime, which seems not to be the case, and is therefore not completely matching OP's question.
You are using inline functions with reified.
To make a long story short, inline functions are compiled and 'copied' to the location where they are being used, already with a fixed (thats what reified does) class. So when you use an inline function
inline fun <reified T> foo(t: T): T { ... }
and you call it like this:
val myVal = foo("test").uppercase()
then at compile time of that calling line of code, the type of T is known to be String and the target line is compiled accordingly, so you know at runtime which type T is within your function.
It is (for this one calling line) as if that function was like this to begin with:
fun foo(t: String): String { ... }
Because you want to compile these classes dynamically, however, this process fails, because the class obviously does not exist yet. This is simply due to the nature of reified. If you can somehow remove it, it might work.
I agree that the error message of the compiler could be more telling here. Maybe you can raise a task on kotlin's issue tracking platform?: https://youtrack.jetbrains.com/issues/kt?_gl=1*5r6x4d*_ga*MTQyMDYxMjc2MS4xNjMzMzQwMzk5*_ga_9J976DJZ68*MTY2OTM1NjM1MS4yMS4xLjE2NjkzNTYzNTcuMC4wLjA.&_ga=2.265829455.1332696793.1669356352-1420612761.1633340399

Kotlin - How to be able to run and test function?

I am creating demo code in Kotlin. I am trying so students should be able:
run function itself
run test
For example:
If function is created in .kt file, outside of class:
fun main(){
print("Hello world!")
}
it can be run
but I could not find the way to call it from the test
If the function is inside the class:
class Hello {
fun main(){
print("Hello world!")
}
}
the function can be called from the test
but can not be run - the green "Run" button is not visible.
Question: How to make such a function can be run manually and by test at the same time?
I'll assume you are writing your tests in Java, because if it's in Kotlin, calling main is trivial: main(), provided that you have imported the package/in the same package.
Kotlin global functions are compiled into static methods of a class with a name similar to the Kotlin file in which the function is declared, suffixed with Kt For example, if the file is called "app.kt", the class name would be AppKt. So if you declared main in app.kt, you would call:
AppKt.main();
in Java
You can change this name by annotating the Kotlin file with #JvmName:
#file:JvmName("MyOwnName")
Then you can call:
MyOwnName.main();
in Java.
See more documentation here

what's the difference between kotlin main functions

what's the difference between this two types of main function in kotlin
fun main(args: Array<String>) {
print("Hello World!")
}
and
fun main() {
print("Hello World!")
}
The syntax with the args is used to pass the parameters to the module from command line interface or from outside program. If you don't need it, you can omit it.
If you are getting started with kotlin I strongly recommend you to look at kotlin official website.
With the first option you could pass arguments when running your program

Kotlin: How to resolve function name clashes when one interface defines a suspend function and the other does not

I had the following problem and was able to resolve the problem by renaming the functions. I am finding myself struggling doing that without my workaround...
How is the following implementation possible without modifying the interfaces:
interface A {
fun test() { }
}
interface B {
suspend fun test()
}
class C : A, B {
suspend fun test(){ // Change that line as you wish
// Implementation
}
Notes: I know of the Kotlin Wiki. But this is more difficult as IntelliJ didn't show that C is a valid implementation of A.
(My problem as far as I know is that one of the interface defines a suspend function and the other does not. My gut feeling is that a non-suspending function should be ok with being implemented as a suspending function, but there does not seem to be such a relation)
Thanks for helping out!

the content in the parameter of the main fun in kotlin

I'm a beginner of Kotlin language and I want to understand everything in this programming language so.
1- what mean of the args: Array<String> in the parameter of the main function ?
2- why compilation error is shown when this line is removed ?
The main(Array<String>) function is an entry point of a program. The strings passed are the command-line arguments.
That is, when you run something like
$ java myprogram foo bar
the main function is called with ["foo", "bar"] as the argument.
This is very much the same thing that Java does, and Java emulates C in this regard.
I keep replacing it with vararg everywhere
object Application {
#JvmStatic
fun main(vararg args: String) {
Micronaut.build()
.packages("example")
.mainClass(Application::class.java)
.start()
}
}
fun main(args : Array<String>) {
println("Hello, world!")
}
In this example, a function named main is defined which returns Unit and takes an Array of strings as a parameter.
Depend on Java convention, this Kotlin code bellow's the same with Java code.
Kotlin code:
fun main(args : Array<String>) {
println("Hello, world!")
}
Java code:
public static void main(String[] args) {
println("Hello, world!");
}
According to #9000 "The main(Array) function is an entry point of a program. The strings passed are the command-line arguments." Each program must have the start entry point. That's just a convention to get the function call parameter.