Make Your Code Clean with Ktlint

Taku Semba
5 min readMar 15, 2018

Kotlin is a new programing language, which has a beautiful syntax. Although people start using kotlin for Android development, it often takes time to discuss the rules how you write Kotlin. This is where ktlint comes in.

Ktlint is a static code analysis tool for kotlin. You can lint your code and even format them.

There are the things that Ktlint can do.

・lint your code and output the result in any way you want like xml, json.

・format your code based off of the result of the lint.

・exclude rules to a specific code or add your own rule.

In this article, I will go through all the Ktlint features from basic usage to custom rule or CI integration.

Topic

  1. Basic Usage
  2. Custom Output
  3. Rule Exclusion
  4. Custom Rule
  5. CI Integration

Basic Usage

It is easy to start ktlint for Android development. Add these lines to your build.gradle.

Now you are ready to start ktlint.

What you have to do now is to add a task for ktlint.

Let’s add two tasks, one is for lint and the other is for format.

You can see these tasks you’ve just created with ./gradlew tasks

Now you can lint your code with ./gradlew ktlint and format them with ./gradlew ktFormat

Custom Output

After you lint your code, ktlint will output the result. There are three types of output. plain, checkstyle, json. or you can even customize the way it outputs.

plain (default)

checkstyle

json

custom output

To customize the output, you need to extend Reporter class

This CustomReporter finds the number of lint errors and output “hello custom reporter” then “found [error num] errors”

Once you defined your custom reporter, just add it to the ReporterProvider

This is the output of your custom reporter

--reporter=custom-ktlint-rule

Rule Exclusion

What if you want to exclude a specific rule? There is a way to do so.

Turn on the --verbose option and add a comment to the line you want to disable rules.

You could also disable rule adding /* ktlint-disable no-wildcard-imports */ until /* ktlint-enable no-wildcard-imports */ (https://medium.com/@shyiko/thanks-for-the-article-taku-semba-bd9898a3c011)

However, It is so much trouble to add a comment to each line.

Unfortunately there is no way to disable a specific rule other than the ways I showed above.

https://github.com/shyiko/ktlint/issues/21

Even though, you can use .editorconfig file to specify your own style. ktlint will look at the .editorconfig first, and lint the code based off of the config file.

Custom Rule

Sometimes you might want to add your own rule to Ktlint. Ktlint is capable of adding a new rule.

First thing you have to do is extend Rule Class and override visit function.

Did you notice the ASTNode argument of the visit function. To add a custom rule, you need to understand what ASTNode is.

What is ASTNode ? AST is shorten for Abstract Syntax Tree.

Any code, regardless of programing language, can be represented as a collection of ASTNode. And They are Tree structured.

For example, the Add function shown above is a ASTNode of KtNamedFunction , and it can be broken into smaller pieces like below.

And these nodes above can be broken into even smaller pieces until it can not be any smaller.

If you do not know what is what ASTNode, --print-ast option will help.

Now that you understood what ASTNode is, let’s dive into how you can add your own custom rule to Ktlint.

Let’s say you want to specify the return type if it is a one-line expression function

First, you make your CustomRule class

Once you’ve defined the custom rule class, add it to RuleSetProvider

Still there are few more steps you have to get through.

Add META-INF/services/com.github.shyiko.ktlint.core.RuleSetProvider file containing a fully qualified name of your provider and make your code into a jar file.

That’s it. Now you can apply your own rule to your code with option -R

If you want to write a test code for your rule, it would look like this.

And make sure the test passes.

CI Integration

You might have thought it is a bit hard to lint-check every time you write code.

Using CI will make your life so much better.

For example, with Danger, you can lint your project when a new pull-request is created and add a comment on GitHub.

I will not get into Danger any deeper for now, but Danger is helpful.

This is how it looks like, when you integrate with Danger.

Lastly

Ktlint is a good choice if you want to keep your kotlin code clean.

--

--