How to Implement a Custom Lint Rule in Android to Warn Against Checked Exception Thrown From Kotlin (Part 3)

Guilherme Krzisch
The Startup
Published in
3 min readSep 21, 2020

While Java introduced the new concept of checked exceptions a few decades ago, Kotlin decided against using it, handling all exceptions as unchecked ones. This can become a point of failure when you are developing an application with both Java and Kotlin code. In this article, we are going to implement an opinionated custom lint rule in order to fill this gap in expectations between these two languages.

Do not throw Exception from Kotlin code

As all Exceptions in Kotlin are unchecked, we should not rely on them to return context to the callers. We should only use them for truly unexpected errors: the good news is that Java already has a class for this type of exceptions, which is the RuntimeException class.

Therefore, for this lint check, we want to detect if our Kotlin code throw Exceptions, either by actually creating and throwing one, or by annotating a method with the @Throws annotation (of course there are perfectly valid cases to annotate a Kotlin method as @Throws, e.g. when it will be called from Java, but as these should be not our common case, we can suppress them individually).

As in the other articles of this series (part 1), we start by declaring the Implementation and the Issue, which encapsulates the Lint error, including the description we want to show for developers. We are considering this issue to be an Error, so it is more severe than other lint warnings.

Our detector class is interested both in methods and in call expressions. The first one, to identify the @Throws annotation, and the second one, to identify throw expressions. For the former, we can simply check, when visiting a method in line 11, if it contains the @Throws annotation; if positive, we can report this as a lint error. For the latter, we create a separate visitor (line 20) to encapsulate its slightly more complex logic.

This visitor is responsible to identify throw expressions in our code (line 4), and then check if the exception this expression is throwing is a checked or a an unchecked exception. If it is an unchecked, there is nothing we should do. Otherwise, we report this as a lint warning, as this is exactly the case we want to detect (Kotlin code throwing checked exceptions).

Finally, to check if an Exception is an unchecked one, we need to verify if its type is RuntimeException (line 14), or if it inherits from it (line 17–18, using recursion).

And done! The complete code can be found here, and the complete set of unit tests here.

Conclusion

You can find the repository with all the examples here. Please fell free to share if you think these rules are useful, and also if you have some ideas of other custom lint checks.

This article is part of a series about creating custom lint rules in Android:
Part 1: How to implement your first custom lint rule in Android using TDD
Part 2: How to implement a custom lint rule in Android that requires an overall view of the project
Part 3: How to implement a custom lint rule in Android to warn against checked exception thrown from Kotlin
Part 4: How to implement a custom lint rule in Android to handle differences in Exception handling between Java and Kotlin
Part 5: How to implement a custom lint rule in Android to detect if we are setting the fragment manager before calling Activity onCreate method
Part 6: (Maybe) How to implement a custom lint rule in Android to detect if we are passing an immutable collection to a Java method which needs a mutable one

--

--

Guilherme Krzisch
The Startup

Software Engineer | Mobile Developer | Android Developer