Skip to content

Custom integration

Warning

This page is based on Ktlint 0.49.x which has to be released. Most concepts are also applicable for 0.48.x.

Ktlint Rule Engine

The Ktlint Rule Engine is the central entry point for custom integrations with the Ktlint API. See basic API Consumer for a basic example on how to invoke the Ktlint Rule Engine. This example also explains how the logging of the Ktlint Rule Engine can be configured to your needs.

The KtLintRuleEngine instance only needs to be created once for the entire lifetime of your application. Reusing the same instance results in better performance due to caching.

Creating the KtLintRuleEngine
val ktLintRuleEngine =
    KtLintRuleEngine(
        ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,
    )

Rule provider

The KtLintRuleEngine must be configured with at least one RuleProvider. A RuleProvider is a lambda which upon request of the KtLintRuleEngine provides a new instance of a specific rule. You can either provide any of the standard rules provided by KtLint or with your own custom rules, or with a combination of both.

Creating a set of RuleProviders
val KTLINT_API_CONSUMER_RULE_PROVIDERS =
    setOf(
        // Can provide custom rules
        RuleProvider { NoVarRule() },
        // but also reuse rules from KtLint rulesets
        RuleProvider { IndentationRule() },
    )

Editor config: defaults & overrides

When linting and formatting files, the KtlintRuleEngine takes the .editorconfig file(s) into account which are found on the path to the file. A property which is specified in the editorConfigOverride property of the KtLintRuleEngine takes precedence above the value of that same property in the .editorconfig file. The editorConfigDefaults property of the KtLintRuleEngine can be used to specify the fallback values for properties in case that property is not defined in the .editorconfig file (or in the editorConfigOverride property).

Specifying the editorConfigOverride
val ktLintRuleEngine =
    KtLintRuleEngine(
        ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,
        editorConfigOverride = EditorConfigOverride.from(
          INDENT_STYLE_PROPERTY to IndentConfig.IndentStyle.SPACE,
          INDENT_SIZE_PROPERTY to 4
        )
    )

The editorConfigOverride property takes an EditorConfigProperty as key. KtLint defines several such properties, but they can also be defined as part of a custom rule.

The editorConfigDefaults property is more cumbersome to define as it is based directly on the data format of the ec4j library which is used for parsing the .editorconfig file.

The defaults can be loaded from a path or a directory. If a path to a file is specified, the name of the file does not necessarily have to end with .editorconfig. If a path to a directory is specified, the directory should contain a file with name .editorconfig. Note that the propertyTypes have to be derived from the same collection of rule providers that are specified in the ruleProviders property of the KtLintRuleEngine.

Specifying the editorConfigDefaults using an '.editorconfig' file
val ktLintRuleEngine =
    KtLintRuleEngine(
        ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,
        editorConfigDefaults = EditorConfigDefaults.load(
            path = Paths.get("/some/path/to/editorconfig/file/or/directory"),
            propertyTypes = KTLINT_API_CONSUMER_RULE_PROVIDERS.propertyTypes(),
        )
  )
If you want to include all RuleProviders of the Ktlint project than you can easily retrieve the collection using StandardRuleSetProvider().getRuleProviders().

The EditorConfigDefaults property can also be specified programmatically as is shown below:

Specifying the editorConfigDefaults programmatically
val ktLintRuleEngine =
    KtLintRuleEngine(
        ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,
        editorConfigDefaults = EditorConfigDefaults(
            org.ec4j.core.model.EditorConfig
                .builder()
                // .. add relevant properties
                .build()
        )
    )

Lint & format

Once the KtLintRuleEngine has been defined, it is ready to be invoked for each file or code snippet that has to be linted or formatted. The the lint and format functions take a Code instance as parameter. Such an instance can either be created from a file

Code from file
val code = Code.fromFile(
    File("/some/path/to/file")
)
or a code snippet (set script to true to handle the snippet as Kotlin script):
Code from snippet
val code = Code.fromSnippet(
    """
    val code = "some-code"
    """.trimIndent()
)

The lint function is invoked with a lambda which is called each time a LintError is found and does not return a result.

Specifying the editorConfigDefaults programmatically
ktLintRuleEngine
  .lint(codeFile) { lintError ->
    // handle
  }

The format function is invoked with a lambda which is called each time a LintError is found and returns the formatted code as result. Note that the LintError should be inspected for errors that could not be autocorrected.

Specifying the editorConfigDefaults programmatically
val formattedCode =
    ktLintRuleEngine
        .format(codeFile) { lintError ->
          // handle
        }

Logging

Ktlint uses the io.github.microutils:kotlin-logging which is a slf4j wrapper. As API consumer you can choose which logging framework you want to use and configure that framework to your exact needs. The basic API Consumer contains an example with org.slf4j:slf4j-simple as logging provider and a customized configuration which shows logging at DEBUG level for all classes except one specific class which only displays logging at WARN level.