How to decapitalize an argument in a Live Template in IntelliJ - intellij-idea

In my project, I have many serialization classes and, to make the classes more readable, I'm standardizing them, with an argument which has the same name of the $class$, that is $argName$:
#immutable
class $class$_Serialize extends Serialize<$class$> {
final $class$ $argName$;
$class$_Serialize(this.$argName$);
#override
Map<String, Object> run() => $serialize$
}
In the Live Template above, the annoyance is that I have to retype $argName$ instead of the template simply decapitalizing $class$. How would I tie $argName$ to the decapitalization of $class$ in IntelliJ?
I've already tried to mess around with editing the variables and adding the decaptialize() function in the expression column, but so far haven't had much success. It was something like this:

You are using the wrong syntax for the decapitalize function. It should look like this:
decapitalize(class)
Note that there are no $ signs around the class in the function argument.

Related

How do I specify an ActionListener in Kotlin?

I want to add an ActionListener to a JButton in Kotlin. In Java, I would just write this:
JPanel makeButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
JButton dirButton = new JButton("Change directory");
dirButton.addActionListener(e -> chooseDirectory());
panel.add(dirButton)
return panel;
}
But it's not so simple in Kotlin. I first tried this:
private fun makeButtonPanel() : JPanel {
val panel = JPanel(FlowLayout())
val dirButton = JButton("Choose")
dirButton.addActionListener(e -> chooseDirectory()) // error message here
// ...
}
private fun chooseDirectory() { ... }
But I'm getting this error message:
Type Mismatch
Required: ((ActionEvent!) -> Unit)!
Found: KFunction1<ActionEvent, Unit>
I understand that the ! means that this is a java method with uncertain nullability, but that doesn't help me understand how to write it. All I want it to do is call the chooseDirectory() method. There must be a clean, simple way to do this, but I don't see it.
As you've discovered, you need to use braces ({ }).
This is because braces are a necessary part of defining a lambda in Kotlin.  (That differs from languages like Java and Scala, where the necessary part is the -> or => arrow.  That's because in Kotlin the arrow is optional if there are one or no parameters; if one, the it keyword is used.)
Without the braces, the code would call your chooseDirectory() function, and try to pass its result to addActionListener() — which obviously wouldn't work.
Braces are also sufficient: they're taken as defining a lambda unless you're giving the body of a function or method or an if/when branch.  (Again, this differs from most C/Java-like languages.  In Kotlin, if you just want a block scope, you have to use a construct such as run.)
As for the parentheses, they're optional here.  You could include them if you wanted:
dirButton.addActionListener({ chooseDirectory() })
But Kotlin has a convention that if a function's last parameter is a function, you can pass it after the parens:
dirButton.addActionListener(){ chooseDirectory() }
And if that would make the parens empty, then you can omit them entirely:
dirButton.addActionListener{ chooseDirectory() }
That's to allow functions that look like new language syntax.  For example, you may have met the with function:
with(someObject) {
itsProperty = someValue
}
That's just a perfectly ordinary function, defined in the standard library, and taking a function as its last parameter.  Similarly, repeat:
repeat(10) {
// Some code to be run 10 times…
}
There's one further thing worth mentioning here.  In Kotlin, lambdas are one way to define functions, which are first-class types and can be defined, passed around, and used just like other types.  This differs from Java, which has traditionally used interfaces for those purposes — often interfaces with a Single Abstract Method (‘SAM interfaces’) — and in which lambdas are little more than syntactic sugar for defining an anonymous implementation of such an interface.
As a special case, for interoperability, Kotlin allows a lambda to define an implementation of a Java SAM interface (or, since Kotlin 1.4, of a Kotlin fun interface), instead of a function.
ActionListener is a Java SAM interface, which is why you can use a lambda here.
Okay, I figured it out, and it was pretty simple. I just have to dispense with the parentheses and say
dirButton.addActionListener { chooseDirectory() }
I'm still not clear on when I should use braces instead of parentheses.

Use extension function from different context in Kotlin

Here is an example of what I'd like to achieve:
open class A {
open fun Int.foo() {
print("foo")
}
}
object B: A() {
val number = 5;
override fun Int.foo() {
print("overriden foo");
// I want to call the A.(Int.foo())
}
}
B.number.foo(); //outputs: "foooverriden foo"
First of all, does anything like this exist? Can I somehow assume number to be in the context of class A in its override method? How would I write this?
The more I think about it the more it twists my mind. Of course, you cannot call number.super.foo() because super for number is kotlin.Number. You cannot cast it to A because Int has nothing to do with A. The only way I can think about solving this to somehow import the extension function itself and rename it with as, but I cannot do that here since it is inside a class, so I cannot just import it. Any suggestions?
My use case for this is that I have a class where I manipulate some data, then in special cases, I want to manipulate it differently, but fall back to the original code as the last option. I could use normal functions instead of extension functions of course, but in my case, it comes natural to use extension functions, so I wanted to see if this could be achieved somehow.
It looks like this is impossible so far, I'm afraid.
There's an open issue for this on JetBrains' issue-tracking system: KT-11488.  There's a Kotlin work-around there, though that needs tweaks to the class designs.
(Also discussed on the JetBrains discussion board.  That mentions another workaround requiring a Java class.)
override fun Int.foo() {
print("overriden foo")
with (A()) {
foo()
}
}
Of course this is a bit of a hack and will get worse if A has some state which foo() depends on, which you'll then need to set manually.

Companion object with extension function in kotlin?

I would like to have extension function and use logger from kotlin-logging and have constants inside companion object.
My function:
fun String.toFoo(): Foo {
logger.debug { "Mapping [$this] to Foo" }
if(MY_CONST.equals(this) {
...
}
Question is where I should put val logger = KotlinLogging.logger {} and MY_CONST since I cannot use companion object with an extension function?
If you just want you logger to be a singleton you can make an object that contains and instance of the logger and reach it from there.
Object LoggerSingleton( val logger = KotlinLogging.logger{})
Then in your extension function
fun String.toFoo(): Foo {
LoggerSingleton.logger.debug { "Mapping [$this] to Foo" }
if(MY_CONST.equals(this) {
}
Since an Object in Kotlin is guaranteed to have only one instance you won't have a different logger for each use of toFoo.
EDIT
To keep the desired class name
Use this signature
Like so:
Object StringLoggerSingleton( val logger = KotlinLogging.logger("String"))
I do not know what you want to accomplish with your logger, but I show you what I did already ;-)
Usually I put extension functions in its own file named similar to what the function is actually extending (e.g. either StringExtensionFunction or if is more related to its purpose and maybe only available if certain dependencies are available, I also did something like, e.g. JsoupExtensionFunctions (where there was a String.toJsoupHtml(), File.toJsoupXml(), etc.)).
If I then need constants I just place them within that file, e.g. by just writing something like:
private const val MY_CONST = "my_const_value"
No surrounding class, no surrounding object.
Regarding the logger... as loggers are usually tied to a certain name/class, I usually put a logger inside every (important) class or associate some logger to specific names... So I am not completely sure what your intent is here... If it's ok for you that the logger is returning the container of your extension function (maybe StringExtensionFunction.kt), then you can also put a logger-val inside that file similar to what I showed with MY_CONST.
If your intention was rather to reuse the callers logger, that might not work so easily... (the easiest would then probably be to pass it to the function, but usually you do not want that)... and other mechanisms may not really be worth it ;-)

Kotlin DSL scope control on external non-changeable classes (similar to #DslMarker)

I have lots of external classes (generated externally; not under my control), which do not come with a builder and which are rather cumbersome to create. However using apply it is rather easy to build them, e.g.:
SomeOfTheObjects().apply {
someProperty = SomeOtherComplexObject().apply {
someOtherProperty = "..."
}
}
Now I like the way it works with the receiver, but I would like to prevent that I can set someProperty within SomeOtherComplexObject. If the classes were under my control, it would suffice to put a #DslMarker on that class, but as they aren't, the only other way that came to my mind, was to use also instead without renaming the parameter, e.g.:
SomeOfTheObjects().also {
it.someProperty = SomeOtherComplexObject().also {
it.someOtherProperty = "..."
//it.someProperty will not work if SomeOtherComplexObject has no such property
}
}
While it works, it now has tons of it. in the code and I was wondering, whether it is possible to have some similar behaviour as with the #DslMarker in place.
What I tried is a mixture of the following:
#DslMarker
annotation class DemoMarker
#DemoMarker
inline fun <T> T.build(#DemoMarker builder : T.() -> Unit) = this.apply(builder)
"mixture", because I ended up putting the annotation everywhere, but this doesn't have any effect. If I put it on a class it works as expected. Did I miss something and it is actually possible somehow? Or does anyone have an appropriate workaround for this, besides using also?
For third party classes you can use the DslMarker annotation on receiver types as explained here.
#DslMarker
#Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE)
annotation class TestDsl
fun build1(builder: (#TestDsl DslReceiver1).() -> Unit) {}

Pass annotation to a function in Kotlin

How can I pass an annotion instance to a function?
I would like to call the java method AbstractCDI.select(Class<T> type, Annotation... qualifiers). But I don't know how to pass an annotation instance to this method.
Calling the constructor like
cdiInstance.select(MyClass::javaClass, MyAnnotation())
is not allowed and the #Annotation-Syntax cdiInstance.select(MyClass::javaClass, #MyAnnotation) is not allowed as parameter, too. How can I archive this?
When working with CDI you usually also have AnnotationLiteral available or at least you can implement something similar rather easy.
If you want to select a class using your annotation the following should do the trick:
cdiInstance.select(MyClass::class.java, object : AnnotationLiteral<MyAnnotation>() {})
Or you may need to implement your specific AnnotationLiteral-class if you require a specific value. In Java that would work as follows:
class MyAnnotationLiteral extends AnnotationLiteral<MyAnnotation> implements MyAnnotation {
private String value;
public MyAnnotationLiteral(String value) {
this.value = value;
}
#Override
public String[] value() {
return new String[] { value };
}
}
In Kotlin however, you can't implement the annotation and extend AnnotationLiteral or maybe I just did not see how (see also related question: Implement (/inherit/~extend) annotation in Kotlin).
If you rather want to continue using reflection to access the annotation then you should probably rather use the Kotlin reflection way instead:
ClassWithAnno::class.annotations
ClassWithAnno::methodWithAnno.annotations
Calling filter, etc. to get the Annotation you desire or if you know there is only one Annotation there, you can also just call the following (findAnnotation is an extension function on KAnnotatedElement):
ClassWithAnno::class.findAnnotation<MyAnnotation>()
ClassWithAnno::methodWithAnno.findAnnotation<MyAnnotation>()
One could annotate a method or field with the annotation an get it per Reflection:
this.javaClass.getMethod("annotatedMethod").getAnnotation(MyAnnotation::class.java)
Or According to Roland's suggestion the kotlin version of the above:
MyClass::annotatedMethod.findAnnotation<MyAnnotation>()!!
As suggested by Roland for CDI it is better to use AnnotationLiteral (see his post).