Pointcut expression to match all public methods in all classes of my application except few packages and classes - aop

I want to match all public methods of all classes of my application(not the dependency library classes) except one class and except classes in one package.
Kotlin class:
#Pointcut("execution(public * com.company.app..*.*(..))")
fun allApplicationCode() {}
#Pointcut("!execution(* * com.company.app.configuration..*.*(..))")
fun notConfigurationPackage() {}
#Pointcut("!execution(* * com.company.app..FlywayConfiguration.*(..))")
fun notFlywayConfigurationClass() {}
#Around("allApplicationCode() && notConfigurationPackage() && notFlywayConfigurationClass()")
fun logExecutionTime(joinPoint: ProceedingJoinPoint): Any {
//code
}
I get error regarding the Pointcut expressions in notConfigurationPackage() and notFlywayConfigurationClass()
Is it a problem if I want to mention "*" explicitly for access modifier?

Related

Verifying method call with enum in Kotlin

I'm trying to verify that a method is called with a given argument. That argument is a non-nullable enum type. So I get the exception eq(SomeEnum.foo) must not be null. Here is a sample what I'm trying to do:
enum class SomeEnum {
foo, bar
}
open class MyClass {
fun doSomething() {
magic(SomeEnum.foo)
}
internal fun magic(whatever: SomeEnum) {}
}
#Test
fun mockitoBug() {
val sut = spy(MyClass())
sut.doSomething()
verify(sut).magic(eq(SomeEnum.foo))
}
Capturing does not work too. What can I do or is that really a bug as I assume?
Because Mockito was designed for Java, it doesn't play well with Kotlin's null checks. A good solution is to use the mockito-kotlin extensions library: https://github.com/mockito/mockito-kotlin
It includes Kotlin versions of the matchers that won't return null. Add a dependency on mockito-kotlin and just make sure to import the Kotlin versions instead of the Java ones.

Add protected and internal visibility to function in kotlin

I have an open (or abstract) public class that contains an open (or abstract) fun (or var or val) that I do not want to expose as public.
Unfortunately I also need to call that fun from inside my current package.
If I mark it as internal that class cannot be inherited correctly from another package(ide gives warning: inherits invisible abstract members), if I mark it as protected the fun cannot be access from inside the current package
Any way to bypass this?
A dirty way is to add a proxy internal method and call that method inside your package:
abstract class AbstractClass {
protected abstract fun isTrue(int: Int): Boolean
internal fun isTrueInternalProxy(int: Int): Boolean {
return isTrue(int)
}
}

Delegate one interface to multiple implementations

Could a class delegate an interface to multiple implementations with a few lines? Given this interface:
interface Foo {
fun doA()
fun doB()
}
The following class would compile for a single delegate:
class FooImpl(delegate: Foo): Foo by delegate
Although useless, it generates java bytecode for what is should do: delegate Foo -> Foo.
Could this be possible for a list of delegates as well? Such that it delegates Foo -> List<Foo>. Like:
class FooImpl(delegates: List<Foo>): Foo by delegates
Right now, our codebase is filled with classes such as:
class FooImpl(private val delegates: List<Foo>): Foo {
override fun doA() { delegates.forEach { it.doA() }
override fun doB() { delegates.forEach { it.doB() }
}
It feels like busy work and it's unnecessarily error prone, plus it creates unneeded work for the dev writing the code and the dev reviewing the code. I'm aware it can become complex for return values, but that will never be the case. In the current code, there's always a set of an interface, 2 actual implementations and a root implementation filled with doA() { delegates.forEach { it.doA() } .
Could this be simplified using Kotlin?

Kotlin multiplatform support for Optional

I'm working with a Java API now converted into multiplatform Kotlin. It used to use java.lang.Optional as the return type of many calls. I understand this is not the idiomatic Kotlin-way (see discussion) but this is an existing API, Optional stays (also it isn't a bad choice for the Java-facing client). My question is how?
Note: The code only needs to return Optional.of(x) or return Optional.empty() to the external API. Any internal uses will be purged.
How do we use expect/actual/typealias to use the real Optional class when available?
Is there a way to avoid re-implementing a fake Optional class on non-Java targets (i.e. work idiomatically with nullable? suffix)
At this point, Kotlin doesn't allow providing an actual typealias for an expected class with a companion object by using a Java class with matching static declarations. Follow this issue for updates: KT-29882.
For now, you can workaround that by declaring the factory functions separately, outside the expected Optional class, as follows:
expect class Optional<T : Any> {
fun get(): T
fun isPresent(): Boolean
/* ... */
}
expect object Optionals {
fun <T : Any> of(t: T): Optional<T>
fun empty(): Optional<Nothing>
}
That should not necessarily be an object, you could just use top-level functions.
Then, on the JVM, you would have to provide an actual typealias for the Optional class and, additionally, provide the trivial actual implementation for the Optionals object:
actual typealias Optional<T> = java.util.Optional<T>
actual object Optionals {
actual fun <T : Any> of(t: T): Optional<T> = java.util.Optional.of(t)
actual fun empty(): Optional<Nothing> = java.util.Optional.empty()
}
As for not providing an implementation for the non-JVM platforms, I doubt it's possible, as that would require some non-trivial compile-time transformations of the Optional usages to just the nullable type. So you would want something like this:
actual typealias Optional<T> = T?
which is now an error:
Type alias expands to T?, which is not a class, an interface, or an object
So you actually need a non-JVM implementation. To avoid duplicating it for every non-JVM target, you can declare a custom source set and link it with the platform-specific source sets, so they get the implementation from there:
build.gradle.kts
kotlin {
/* targets declarations omitted */
sourceSets {
/* ... */
val nonJvmOptional by creating {
dependsOn(getByName("commonMain"))
}
configure(listOf(js(), linuxX64())) { // these are my two non-JVM targets
compilations["main"].defaultSourceSet.dependsOn(nonJvmOptional)
}
}
}
Then, inside this custom source set (e.g. in src/nonJvmOptional/kotlin/OptionalImpl.kt) you can provide an actual implementation for the non-JVM targets.
Here's a minimal project example on Github where I experimented with the above: h0tk3y/mpp-optional-demo

Kotlin Wildcard Capture on List Callback Parameter

Java:
public class JavaClass implements ModelController.Callback {
#Override
public void onModelsLoaded(#NonNull List<? extends Model> models) {
doSomething(models);
}
private void doSomething(List<Model> models) { }
}
Kotlin:
class ModelController {
var callback = WeakReference<Callback>(null)
interface Callback {
fun onModelsLoaded(models: List<Model>)
}
fun someFunction() {
callback.get().onModelsLoaded(ArrayList<Model>())
}
}
interface Model {
}
Without the ? extends Model in the Java onModelsLoaded method, the override doesn’t match the interface made in Kotlin. With it, I get the following error:
doSomething(<java.util.List<com.yada.Model>) cannot be applied to (java.util.List<capture<? extends com.yada.Model>>)
Why is the wildcard capture required and why doesn't it allow it to be used against the non-wildcard method?
The issue stems from Kotlin collections being variant, and Java only having use-site variance which is implemented though wildcards (capture is something connected to wildcards but not exactly the ? extends ... syntax itself).
When in Kotlin we say List<Model> it means "read-only list of Model or subtypes of Model", when we say the same in Java it means "mutable list of exactly Model and nothing else". To mean roughly what Kotlin's List<Model> means, in Java we have to say List<? extends Model>, this is why for the override to work you have to add the wildcard into the Java code.
Now, your doSomething is written in Java and says that it wants "a list of exactly Model", and when you are giving it "a list of Model or its subtypes", the Java compiler complains, because it can be dangerous: doSomething might try to do something that is not legitimate for a list of, say, ModelImpl, because it thinks it's working on a list of Model.
As of now (Kotlin Beat 2), you have two options:
use MutableList<Model> in your Kotlin code - this mean exactly what Java's List<Model> means, or
define doSomething so that it takes List<? extends Model>, which is what your current Kotlin code means.
In the next update of Kotlin we'll add an annotation on types to facilitate a somewhat cleaner workaround for this problem.
To solve the problem with capture<? extends Model>
You may do something like this:
void doSomething(List<Model> models) {
new ArrayList(models)
}