kotlin multi-platform to javascript : naming of the method not respected - kotlin

I use the gradle kotlin multi-platform plugin to build something in java and js
My issue is in the js version, the name of the function/class is not consistent:
in my kotlin, I define a function "launch()", in the js buid, it will be "launch12434()"
any idea how to correct-it?

You can use the #JsName annotation to give a specific name for your method. It looks like this;
#JsName("launch")
fun launch() {
}
More info here.

Related

How can I navigate to Lombok generated implementations

I'm wondering if it would be possible to navigate directly to the methods generated by Lombok using Intellij IDEA.
For instance, for this given example:
#Builder
public class AClass {
private String body;
}
trying to go to the implementation of AClass#builder in an instruction like AClass.builder().build() results in Intellij navigating to AClass, instead of taking me to the real compiled method, which is generated under target directory
Please feel free to create an issue here: https://youtrack.jetbrains.com/issues/IDEA
Currently you can't change the behavior.

How to import KotlinMultiplatformExtension inside buildSrc module?

I am developing a kotlin multiplatform project, which has a bunch of modules.
I have written an extension function which is meant to be used inside each module. The extension function extends functionality of KotlinMultiplatformExtension class. Now that code is repeated inside each module's build.gradle.kts file. So i thought it would be great to move that code to buildSrc moudle and reuse everywhere.
The problem is that inside buildSrc module KotlinMultiplatformExtension is not resolved.
My buildSrc/build.gradle.kts:
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
If i right click KotlinMultiplatformExtension inside someModule/build.gradle.kts
it takes me to:
So I guessed that adding a dependency inside buildSrc/build.gradle.kts should help:
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
}
But adding that results with an error:
* Exception is:
java.lang.NoClassDefFoundError: com/android/build/gradle/BaseExtension
at org.jetbrains.kotlin.gradle.plugin.AbstractAndroidProjectHandler.configureTarget(KotlinPlugin.kt:765)
at org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin$Companion.applyToTarget(KotlinPlugin.kt:727)
at org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin.apply(KotlinPlugin.kt:689)
at org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPlugin.apply(KotlinPlugin.kt:678)
at org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper.apply(KotlinPluginWrapper.kt:102)
Any ideas how to make KotlinMultiplatformExtension available inside buildSrc?
Turns out that changing
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
into
compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
resolves problem with the exception (java.lang.NoClassDefFoundError: com/android/build/gradle/BaseExtension)
and makes KotlinMultiplatformExtension available inside the buildSrc's source files.
solution found here:
https://github.com/gradle/gradle/issues/9209

Intellij IDEA plugin development. Action "create kotlin class"

I want to create a plugin for Intellij IDEA. I need to add an action (AnAction) that will create a class in Kotlin (not Java) in a custom package. I have two questions:
How to create files with the desired extension?
Or how to create a file with Kotlin class(from some base class) in a custom package?
One possible way to accomplish this is to use PsiFileFactory.createFileFromText() to create an in-memory Kotlin file and then to pass that file as a parameter to PsiDirectory.add() to save it to the filesystem.
Although yole's answer is correct, I would like to see more details about mistery PsiDirectory class.
//get directory by VirtualFile
PsiDirectory directory = PsiManager.getInstance(project).findDirectory((getKotlinSourceDir(project))
Get kotlin source dir:
private VirtualFile getKotlinSourceDir(Project project) {
return project.getBaseDir().findChild("src").findChild("main").findChild("kotlin");
}
And than you can create subdirectories:
//someDirectoryName it is simple name
//(i.e if you post "com.some.package" - it does not create com/some/package folder)
PsiDirectory newDirectory = psiDirectory.createSubdirectory(someDirectoryName);

Kotlin synthetic in Adapter or ViewHolder

I am new in kotlin. I have found and tried to use synthetic method instead of annoying method findViewById in my Activity class, but I have found "If we want to call the synthetic properties on View (useful in adapter classes), we should also import kotlinx.android.synthetic.main.view.*." But I can't figure out how it exactly works? Is there any examples?
Simple example from https://github.com/antoniolg/Kotlin-for-Android-Developers
import kotlinx.android.synthetic.item_forecast.view.*
class ForecastListAdapter() : RecyclerView.Adapter<ForecastListAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindForecast(forecast: Forecast) {
itemView.date.text = forecast.date.toDateString()
}
}
}
No need to write
val view = itemView.findViewById(R.id.date) as TextView
view.text = forecast.date.toDateString()
Just
itemView.date.text = forecast.date.toDateString()
Simple and effective!
Kotling 1.1.4 out
Further information : https://antonioleiva.com/kotlin-android-extensions/
You need to enable Kotlin Android Extentions by adding this to your build.gradle:
apply plugin: 'org.jetbrains.kotlin.android.extensions'
androidExtensions {
experimental = true
}
Since this new version of Kotlin, the Android Extensions have incorporated some new interesting features: caches in any class (which interestingly includes ViewHolder)
Using it on a ViewHolder (or any custom class). Note that this class should implement LayoutContainer interface:
class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
LayoutContainer {
fun bind(title: String) {
itemTitle.text = "Hello Kotlin!"
}
}
You need
import kotlinx.android.synthetic.row_wall.view.*
And later something along the lines of:
convertView.titleText.text = item.title
The point is that the view.* introduces extensions to the View class.
Try
class CustomViewModel(val baseView: View) {
val firstName = baseView.firstName
val lastName = baseView.lastName
}
View object exposes the views
ref:https://discuss.kotlinlang.org/t/unable-to-use-kotlin-android-extension-in-adapter-class/2890
If you are using the latest version l;.you don't have to add experimental = true to it.
in Project level Gradle
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21'
And in app level Gradle
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //These should be on the top of file.
and in dependencies..
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21'
and import below as
import kotlinx.android.synthetic.main.your_layout_file_name.view.*
and example
import kotlinx.android.synthetic.main.item_animal.view.*
class AnimalVH(parent: ViewGroup, layoutID: Int) : BaseViewHolder<Animal>(parent, layoutID) {
override fun bindData(animal: Animal) {
itemView.tv_animal.text = animal.title
}
}
where BaseViewHolder is
abstract class BaseViewHolder<T>(parent: ViewGroup, layoutID: Int) : RecyclerView.ViewHolder(
LayoutInflater.from(parent.context).inflate(layoutID, parent, false)
) {
abstract fun bindData(model: T)
}
It means you have to place this line at the beginning of your source file:
import kotlinx.android.synthetic.main.view.*
So now instead of, for example, findView(R.id.textView) as TextView you would write just textView. The latter is a synthetic extension property located in the package kotlinx.android.synthetic.main.view, that's why you have to import everything from it.
There's a tutorial on the official site, take a look.
FYI: Data binding is recommended over synthetic for view lookups.
Comment from a DA for Android from Google on Reddit
Hey! Developer Advocate for Android at Google here!
I wanted to add a bit of background here. Kotlin Extensions with
synthetic views was never intentionally “recommended” though that
shouldn’t be taken as a recommendation to not use them. If they're
working for you please feel free to continue using them in your app!
We’ve been shifting away from them (e.g. we don’t teach them in the
Udacity course) because they expose a global namespace of ids that’s
unrelated to the layout that’s actually inflated with no checks
against invalid lookups, are Kotlin only, and don't expose nullability
when views are only present in some configuration. All together, these
issues cause the API to increase number of crashes for Android apps.
On the other hand, they do offer a lightweight API that can help
simplify view lookups. In this space it's also worth taking a look at
Data Binding which also does automatic view lookups - as well as
integrates with LiveData to automatically update your views as data
changes.
Today, there's a few options in this space that work:
Data Binding is the recommendation for view lookup as well as binding,
but it does add a bit of overhead when compared to Android Kotlin
Extensions. It's worth taking a look to see if this is a good fit for
your app. Data Binding also allows you to observe LiveData to bind
views automatically when data changes. Compared to Kotlin Extensions,
it adds compile time checking of view lookups and type safety. Android
Kotlin Extensions is not officially recommended (which is not the same
as recommendation against). It does come with the issues mentioned
above, so for our code we're not using them. Butter Knife is another
solution that is extremely popular and works for both Kotlin and the
Java Programming Language. Reading through the comments here there's a
lot of developers that are having great luck with Kotlin Extensions.
That's great - and something we'll keep in mind as we look at ways to
continue improving our APIs. If you haven't taken a look at Data
Binding, definitely give it a shot.
As an aside, our internal code style guide is not intended to be
directly applied outside of our codebase. For example, we use
mPrefixVariables, but there's no reason that every app should follow
that style.

Intellij idea: how to extend the Java editor

I have managed to develop and run an intellij plugin. Would it be possible to create a plugin extending the java editor for instance by providing a custom code completion feature ?
Yes, this is possible. Please refer to the JavaDoc of the CompletionContributor class for details of implementing custom code completion.