Generate kotlin file from parsed KtFile? - kotlin

I am using kotlin embeddable compiler to parse some kotlin files into the KtFile instances.
Is there a way to modify KtFile and generate new kotlin file content? Something like converting KtFile into, e.g. Kotlin Poet classes?

Related

How to use Kotlin compiler library to analyze external project

I have a problem with processing Kotlin source code via kotlin-compiler-embeddable. I need to obtain PSI class representations for all classes in an external project, build them, and get BindingContext, but I can't find any examples.
I would like to use the kotlin-compiler-embeddable library to analyse dependencies in a Kotlin project outside the IntelliJ environment.
I manage to obtain PSI representations for individual classes. Unfortunately this is not enough. I would like to track dependencies between classes.
private val project by lazy {
KotlinCoreEnvironment.createForProduction(
Disposer.newDisposable(),
CompilerConfiguration(),
EnvironmentConfigFiles.JVM_CONFIG_FILES
).project
}
fun createKtFile(codeString: String, fileName: String) =
PsiManager.getInstance(project)
.findFile(
LightVirtualFile(fileName, KotlinFileType.INSTANCE, codeString)
) as KtFile
For example, I need to get a PSI Class representation or fully-qualified class name for the service parameter type.
class ShapeEndpoint(service: ShapeService)
Is there somewhere a comprehensive example that would show how to compile a group of source files, build a BindingContext, access it and then use it effectively?

Kotlin Data Classes support in Protobuf

I am implementing protobuf recently in our kotlin project.
I am receiving the binary data and deserialising it to Proto object using the proto file.
But I would like have that converted to data class.
I could not find any supporting information about how to do this.
Is it possible to get data class from binary data or from deserialized proto object??
One solution might be to use pb-and-k which has the kotlin code generator and will generate data classes for you based off of the .proto files
If you have know the structure of the data and can write your data classes upfront, you might want to have a look at kotlinx.serialization. It is an official Kotlin project and supports protobuf out-of-the-box.

In Kotlin How to read and parse json file

I am new to Kotlin and trying to understand how I can read and parse the .json file.
Say, I have a file Test.json with some json array and need to read the array and stored the content in mutable list.
I tried searching the blog but could not find the answer.
Thanks in advance.
It depends, if you know the format of the JSON file maps to one of your Kotlin classes then you could use a library such as Jackson, Gson, Klaxon or Moshi to convert the contents of the file to an instance of this class.
Alternatively you could manually parse the JSON using Java's JSONObjects and work through the nested map of JsonObjects/Values.
I personally use this Klaxon library to parse json file and use in in my android application.
which I think will do your work.
Add dependncy to your gradle.build file
compile 'com.beust:klaxon:0.30'

modify a Kotlin class

I'd like to write a plugin for Intellij IDEA that should modify a Java and Kotlin code.
I use the method
PsiClass.getMethods()
in order to get all methods of Java and Kotlin classes. So far so good, so then I use methods like
PsiClass.add(), PsiClass.addAfter(), PsiClass.addBefore()
that all work fine once they are called on Java files, but start to throw an exception
IncorrectOperationException
once I called them on a Kotlin class.
I'd appreciate any hint on how I can modify Kotlin and Java classes (preferably using the same approach).
When you search for a Kotlin class via the JavaPsiFacade, it returns the light class which is a shallow representation that is just based on the information in the class file. In order to add PSI elements, you have to call navigationElement on it. Then, IJ will parse the source and build a full PSI tree that can be modified.
However, if the class is a Kotlin class, navigationElement will return a KtClass which is not derived from PsiClass. You will have to use the facilities in the Kotlin hierarchy to modify it. Method instances in Kotlin are also not instances of PsiMethod, but instances of KtMethod.
For analyzing Java and Kotlin sources in a common fashion there is a different syntax tree called "UAST", but for modifications you need a language-specific approach.

How to generate a kotlin file from an annotation processor?

I have a java annotation processor which generates a bunch of java files during compilation. I'd like to make the generated classes nicer to use in kotlin by adding extension methods. I've been told on the kotlin forums that something I could try would be to write a kotlin file that contains my extension functions. I've tried this, I used the Filer object to create this file outputting it to the StandardLocations.SOURCE_OUTPUT directory. Intellij can see my generated class, and I can use the extension functions as intended, but the app won't compile because the compiler can't find the new kotlin file. Is there any way I can write a new kotlin file that'll get picked up by the kotlin compiler?
For kapt you can get source folder via.
Map<String, String> options = processingEnv.getOptions();
String generatedPath = options.get("kapt.kotlin.generated");
String path = generatedPath
.replaceAll("(.*)tmp(/kapt/debug/)kotlinGenerated",
"$1generated/source$2");
Unfortunately it doesn't work for kapt2 (see issue KT-14070)
You also can create .kt files via resource writer
Writer w = processingEnv.getFiler().createResource(SOURCE_OUTPUT, "package_name", "Sample.kt")
But for now you need to invoke compiler twice cause compileDebugKotlin task runs before invoking javax annotation processor by compileDebugJavaWithJavac task)
Output your files (with proper package names) into a directory like src/build/generated-src/kotlin/your/package/File.kt
and add this to your build.gradle:
sourceSets {
main.java.srcDirs += 'build/generated-src/kotlin'
}