https://kotlinlang.org logo
#detekt
Title
m

Michael Marshall

06/07/2021, 2:02 AM
I've got a custom detekt rule with type resolution and I'm receiving the
bindingContext
okay, but
getType
is always
null
. What should I be doing to get the class of the object declaration?
Copy code
override fun visitObjectDeclaration(declaration: KtObjectDeclaration) {
    super.visitObjectDeclaration(declaration)

    if (bindingContext == BindingContext.EMPTY) return

    if (bindingContext.getType(declaration) is Serializable) {
        report(
            CodeSmell(
                issue = issue,
                entity = Entity.from(declaration),
                message = "Do not use Java Serialization for Kotlin objects."
            )
        )
    }
}
I have also tried, from various internet sources 1.
Copy code
(declaration.resolve() as? ClassDescriptor)?.defaultType
resolve() method not found 2.
Copy code
(declaration as KtCallableDeclaration).createTypeBindingForReturnType(bindingContext)?.type
cast fails 3.
Copy code
declaration.kotlinType(bindingContext)
always null
g

gammax

06/07/2021, 9:35 AM
You should be good with:
Copy code
declaration.superTypeListEntries.any { it.text == "Serializable" }
m

Michael Marshall

06/07/2021, 9:41 AM
Hey thanks for that, although I need to check the whole class hierarchy for Serializable, not just if it's a direct super class
That's why I needed the type resolution, to perform the
is Serializable
check
g

gammax

06/07/2021, 10:08 AM
I believe you should then use:
Copy code
bindingContext[BindingContext.CLASS, declaration]?.defaultType
m

Michael Marshall

06/07/2021, 10:29 AM
That works almost! It still fails the
is Serializable
check, I think it's a
SimpleTypeImpl
rather than the actual class, or something lazy?
Also is there any documentation for this? 😅
g

gammax

06/07/2021, 11:05 AM
So the
is Serializable
check is most likely a bad approach. I believe you should reach a fully qualified type in some form and then do a string comparison with
java.io.Serializable
. As for the documentation, that’s Kotlin PSI & the compiler API. Really bad documented 😞 That’s a known issue on JetBrains table.
Also my approach is generally to use the debugger. Like you add a breakpoint inside the rule, and then you try to evaluate expressions like the one I mentioned before. A bit of trial-n-error 🙂
m

Michael Marshall

06/07/2021, 11:07 AM
Yeah it's been an absolute slog piecing together clues from around the internet 😂
If I can't use
isSerializable
then I'll need to recurse up the whole class hierarchy won't I?
In fact, if I can't get the class, I won't be able to do that either...
g

gammax

06/07/2021, 11:55 AM
then I’ll need to recurse up the whole class hierarchy won’t I?
Mmm not really. I believe that with type resolution, you should be able to get all the implemented interfaces, also the one of your superclasses..
😮 1
m

Michael Marshall

06/07/2021, 2:34 PM
I didn't realise it could do that, thanks for the help! Got it working with this
Copy code
private val KtObjectDeclaration.isJavaSerializable
        get() = bindingContext[BindingContext.CLASS, this]
            ?.defaultType
            ?.supertypes()
            ?.any { it.fqNameOrNull()?.asString() == "java.io.Serializable" } == true
g

gammax

06/07/2021, 3:21 PM
Awesome 🚀
32 Views