diff --git a/1.4.0/install/cli/index.html b/1.4.0/install/cli/index.html index e34d0ec359..25ebc11fb0 100644 --- a/1.4.0/install/cli/index.html +++ b/1.4.0/install/cli/index.html @@ -1501,7 +1501,6 @@

Package managersMacPorts
port install ktlint
 

-

On Arch Linux install package ktlint AUR.

Command line usage

Rule set(s)

When no arguments are specified, the style of all Kotlin files (ending with '.kt' or '.kts') inside the current dir (recursively) are validated with the rules from the standard ruleset. Hidden folders will be skipped.

diff --git a/1.4.0/search/search_index.json b/1.4.0/search/search_index.json index 5f3dcbc5c6..852c28fe4f 100644 --- a/1.4.0/search/search_index.json +++ b/1.4.0/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome to Ktlint","text":"

Kotlin linter in spirit of feross/standard (JavaScript) and gofmt (Go).

"},{"location":"#features","title":"Features","text":""},{"location":"#legal","title":"Legal","text":"

This project is not affiliated with nor endorsed by JetBrains. All code, unless specified otherwise, is licensed under the MIT license. Copyright \u00a9 2019 Pinterest, Inc. Copyright \u00a9 2016-2019 Stanley Shyiko.

"},{"location":"faq/","title":"FAQ","text":""},{"location":"faq/#why-should-i-use-ktlint","title":"Why should I use ktlint?","text":"

the short answer is Simplicity.

Spending time on configuration (and maintenance down the road) of hundred-line long style config file(s) is counter-productive. Instead of wasting your energy on something that has no business value - focus on what really matters (not debating whether to use tabs or spaces).

By using ktlint you put the importance of code clarity and community conventions over personal preferences. This makes things easier for people reading your code as well as frees you from having to document and explain what style potential contributor(s) have to follow.

ktlint is a single binary with both linter & formatter included. All you need is to drop it in (no need to get overwhelmed while choosing among dozens of code style options).

"},{"location":"faq/#what-are-the-maven-coordinates-in-ktlint-1x","title":"What are the Maven coordinates in Ktlint 1.x?","text":"

With the release of ktlint 1.0 the Maven coordinates of most modules have been changed. Now all ktlint modules are published in Maven group com.pinterest.ktlint. Also, the artifact id's of some modules have been changed.

The Maven coordinates of modules below have been changed:

Old Maven coordinates New Maven coordinates com.pinterest:ktlint com.pinterest.ktlint:ktlint-cli com.pinterest.ktlint:ktlint-reporter-baseline com.pinterest.ktlint:ktlint-cli-reporter-baseline com.pinterest.ktlint:ktlint-reporter-checkstyle com.pinterest.ktlint:ktlint-cli-reporter-checkstyle com.pinterest.ktlint:ktlint-cli-reporter com.pinterest.ktlint:ktlint-cli-reporter-core com.pinterest.ktlint:ktlint-reporter-format com.pinterest.ktlint:ktlint-cli-reporter-format com.pinterest.ktlint:ktlint-reporter-html com.pinterest.ktlint:ktlint-cli-reporter-html com.pinterest.ktlint:ktlint-reporter-json com.pinterest.ktlint:ktlint-cli-reporter-json com.pinterest.ktlint:ktlint-reporter-plain com.pinterest.ktlint:ktlint-cli-reporter-plain com.pinterest.ktlint:ktlint-reporter-plain-summary com.pinterest.ktlint:ktlint-cli-reporter-plain-summary com.pinterest.ktlint:ktlint-reporter-sarif com.pinterest.ktlint:ktlint-cli-reporter-sarif"},{"location":"faq/#how-do-i-enable-or-disable-a-rule","title":"How do I enable or disable a rule?","text":"

An individual rule can be enabled or disabled with a rule property. The name of the rule property consists of the ktlint_ prefix followed by the rule set id followed by a _ and the rule id. Examples:

ktlint_standard_final-newline = disabled # Disables the `final-newline` rule in the `standard` rule set provided by KtLint\nktlint_standard_some-experimental-rule = enabled # Enables the (experimental) `some-experimental-rule` in the `standard` rule set provided by KtLint\nktlint_custom-rule-set_custom-rule = disabled # Disables the `custom-rule` rule in the `custom-rule-set` rule set (not provided by KtLint)\n

Note

The rule properties are applied after applying the rule set properties and take precedence. So if a rule set is disabled but a specific rule of that rule set is enabled, then the rule will be executed.

"},{"location":"faq/#how-do-i-enable-or-disable-a-rule-set","title":"How do I enable or disable a rule set?","text":"

All rules in a rule set can be enabled or disabled with a rule set property. The name of the rule set property consists of the ktlint_ prefix followed by the rule set id. Examples:

ktlint_standard = disabled # Disable all rules from the `standard` rule set provided by KtLint\nktlint_experimental = enabled # Enable rules marked as experimental for all rule sets that are enabled\nktlint_custom-rule-set = enabled # Enable all rules in the `custom-rule-set` rule set (not provided by KtLint)\n

Note

All rules from the standard and custom rule sets are enabled by default and can optionally be disabled in the .editorconfig. All experimental rules are disabled by default and can optionally be enabled in the .editorconfig.

"},{"location":"faq/#why-is-a-rule-skipped-when-i-disable-some-other-rule","title":"Why is a rule skipped when I disable some other rule?","text":"

Most rules in ktlint can be executed independently of other rules. However, some rules can only be executed in case one or more other rules are also loaded and/or enabled. Dependencies between rules are introduced to reduce complexity in ktlint. Similar logic in different rules has to be avoided as this might result in formatting conflicts between different rules, which could result in endless loops of formatting and reformatting by a set of rules.

In case, you disable a rule, you might run into an IllegalStateException like below:

java.lang.IllegalStateException: Skipping rule(s) which are depending on a rule which is not loaded. Please check if you need to add additional rule sets before creating an issue.\n  - Rule with id 'RuleId(value=standard:string-template-indent)' requires rule with id 'RuleId(value=standard:multiline-expression-wrapping)' to be loaded\n

For the example above, the string-template-indent rule depends on the multiline-expression-wrapping so that the former rule does not need to know, how to wrap a multiline string that is not yet wrapped:

val foo = \"\"\"\n    some text\n   \"\"\".trimIndent()\n

"},{"location":"faq/#why-does-ktlint-discourage-certain-comment-locations","title":"Why does ktlint discourage certain comment locations?","text":"

Kotlin has three different type of comments. Although the KDoc and the block comment look similar in code, their internal PSI structure is different. The EOL comment is yet very different.

In Kotlin it is possible to insert a comment everywhere. It is very challenging, and time-consuming, to make each rule fully resilient for each possible comment location, even in case such locations will (almost) never by used.

For example, in sample below it is unclear whether the comment applies to the if block, or to the else block without interpreting the comment itself.

Unclear comment Clear comment
if (someCondition) {\n    doTrue()\n} // comment\nelse {\n    doFalse()\n}\n
if (someCondition) {\n    doTrue()\n} else { \n    // comment\n    doFalse()\n}\n

In other cases, a comment location is more widely used but semantically still incorrect. For example, in sample below the EOL comment is placed after the comma, but it obviously is related to the part before the comma:

Unclear comment Clear comment
fun fooBar(\n    foo: Foo, // foo-comment\n    bar: Bar, // bar-comment\n) {}\n
fun fooBar(\n    // foo-comment\n    foo: Foo,\n    // bar-comment\n    bar: Bar,\n) {}\n

By forbidding certain comment locations, the logic in the rules becomes a bit easier.

"},{"location":"faq/#can-i-have-my-own-rules-on-top-of-ktlint","title":"Can I have my own rules on top of ktlint?","text":"

Absolutely, \"no configuration\" doesn't mean \"no extensibility\". You can add your own ruleset(s) to discover potential bugs, check for anti-patterns, etc.

See adding a custom rule set for more information.

"},{"location":"faq/#how-do-i-suppress-errors-for-a-lineblockfile","title":"How do I suppress errors for a line/block/file?","text":"

Tip

Suppressing a ktlint violation is meant primarily as an escape latch for the rare cases when ktlint is not able to produce the correct result. Please report any such instances using GitHub Issues).

To disable a specific rule you'll need the fully qualified rule identifier. This identifier is displayed at the end of the lint error. In case your code was autocorrected, you need to revert the code and run the lint task instead of the format to find the rule identifier.

As of Ktlint 0.50, an error can only be suppressed using @Suppress or @SuppressWarnings annotations

Warning

Import statements can not be annotated in Kotlin. The rules related to import statements can be suppressed with file annotations only.

Allowed
// Suppressing all rules for the entire file\n@file:Suppress(\"ktlint\")\n\n// Suppressing specific rules for the entire file\n// Rules related to import statements can only be suppressed using file annotations\n@file:Suppress(\"ktlint:standard:no-wildcard-imports\", \"ktlint:custom-rule-set-id:custom-rule-id\")\n\n// Suppress all rules for the annotated construct\n@Suppress(\"ktlint\")\nclass Foo {}\n\n// Suppress a single rule (with id 'rule-id', defined in rule set with id 'rule-set-id') in the scope of the annotated construct\n@Suppress(\"ktlint:rule-set-id:rule-id\")\nclass Foo {}\n
"},{"location":"faq/#why-is-editorconfig-property-disabled_rules-deprecated-and-how-do-i-resolve-this","title":"Why is .editorconfig property disabled_rules deprecated and how do I resolve this?","text":"

The .editorconfig properties disabled_rules and ktlint_disabled_rules are deprecated as of KtLint version 0.48 and are removed in version 0.49. Those properties contain a comma separated list of rules which are disabled. Using a comma separated list of values has some disadvantages.

A big disadvantage is that it is not possible to override the property partially in an .editorconfig file in a subpackage. Another disadvantage is that it is not possible to express explicitly that a rule is enabled. Lastly, (qualified) rule ids can be 20 characters or longer, which makes a list with multiple entries hard to read.

Starting with KtLint 0.48 entire rule sets and individual rules can be disabled / enabled with a separate property per rule (set). Examples:

ktlint_standard = disabled # Disable all rules from the `standard` rule set provided by KtLint\nktlint_standard_final-newline = enabled # Enables the `final-newline` rule in the `standard` rule set provided by KtLint\nktlint_experimental = enabled # Enable rules marked as experimental for all rule sets that are enabled\nktlint_standard_some-experimental-rule = disabled # Disables the (experimental) `some-experimental-rule` in the `standard` rule set provided by KtLint\nktlint_custom-rule-set = enabled # Enable all rules in the `custom-rule-set` rule set (not provided by KtLint)\nktlint_custom-rule-set_custom-rule = disabled # Disables the `custom-rule` rule in the `custom-rule-set` rule set (not provided by KtLint)\n

Note

All rules from the standard and custom rule sets are enabled by default and can optionally be disabled in the .editorconfig. All experimental rules are disabled by default and can optionally be enabled in the .editorconfig.

Note

The rule properties are applied after applying the rule set properties and take precedence. So if a rule set is disabled but a specific rule of that rule set is enabled, then the rule will be executed.

"},{"location":"faq/#why-is-wildcard-import-javautil-not-reported-by-the-no-wildcard-imports-rule","title":"Why is wildcard import java.util.* not reported by the no-wildcard-imports rule?","text":"

The no-wildcard-imports rule forbids wildcard imports, except for imports defined in .editorconfig property ij_kotlin_packages_to_use_import_on_demand. If this property is not explicitly set, it allows wildcards imports like java.util.* by default to keep in sync with IntelliJ IDEA behavior.

"},{"location":"faq/#can-a-new-toggle-be-added-to-optionally-enabledisable-format-code-in-a-particular-way","title":"Can a new toggle be added to optionally (enable/disable) format code in a particular way?","text":"

Ktlint can be configured by enabling and disabling rules. Some rules can be configured in more details with additional .editorconfig properties. Regularly, a new configuration option is requested to modify behavior in existing rules.

Ktlint is restrictive with adding additional configuration settings to customize behavior in rules. Each configuration option that Ktlint offers comes with complexity that has to be maintained by only a couple of maintainers. As of that, we cannot provide tens or even hundreds of such options.

Less configuration options also means less discussions in teams about settings to use. Unfortunately this means that you cannot tweak Ktlint exactly to the format you prefer.

Tip

Any idea for a new configuration option is valuable. Please create an issue for it so that it can be considered to incorporate it in Ktlint.

"},{"location":"faq/#can-i-use-ktlint-to-directly-format-the-code-im-generating-with-kotlinpoet","title":"Can I use KtLint to directly format the code I'm generating with KotlinPoet?","text":"

Yes, it is possible to use KtLint to directly format the code generated with KotlinPoet. To do so, you must include the dependencies com.pinterest.ktlint:ktlint-core and com.pinterest.ktlint:ktlint-ruleset-standard in your Gradle/Maven project.

Warning

Do not include the dependency com.pinterest.ktlint:ktlint-cli as that would import the entire ktlint project including unwanted dependencies. Besides a much bigger artifact, it might also result in problems regarding logging.

To format the output of KotlinPoet with KtLint, you can use the following snippet:

val ruleProviders = buildSet {\n  ServiceLoader\n      .load(RuleSetProviderV2::class.java)\n      .flatMapTo(this) { it.getRuleProviders() }\n}\nval ktLintRuleEngine = KtLintRuleEngine(\n  ruleProviders = ruleProviders,\n  editorConfigDefaults = EditorConfigDefaults.load(EDITORCONFIG_PATH),\n)\nktLintRuleEngine.format(outputDir.toPath())\n
Here, outputDir refers to the directory of the generated files by KotlinPoet, ktLintRuleEngine is an instance of KtLint rule engine.

It is also possible to format file-by-file the output of KotlinPoet if you write your FileSpec to a StringBuilder(), instead of a File, and send the generated code as String to KtLint inside a CodeSnippet:

kotlinFile.writeText(\n  ktLintRuleEngine.format(\n    Code.CodeSnippet(\n      stringBuilder.toString()\n    )\n  )\n)\n

"},{"location":"faq/#are-formatter-tags-respected","title":"Are formatter tags respected?","text":"

As of version 0.49.x the formatter tags of IntelliJ IDEA are respected. By default, those formatter tags are disabled. The formatter tags can be enabled with .editorconfig properties below:

ij_formatter_tags_enabled = true # Defaults to 'false'\nij_formatter_off_tag = some-custom-off-tag # Defaults to '@formatter:off'\nij_formatter_on_tag = some-custom-on-tag # Defaults to '@formatter:on'\n

When enabled, the ktlint rule checking is disabled for all code surrounded by the formatter tags.

"},{"location":"faq/#how-do-i-disable-ktlint-for-generated-code","title":"How do I disable ktlint for generated code?","text":"

Running ktlint on generated code is not useful. Fixing lint and format errors on generated code is a waste of time as errors will be re-introduced once that code is generated again. Given that generated code is located in a separate directory, you can disable ktlint for such directory by adding a glob for that directory:

[some/path/to/generated/code/**/*]\nktlint = disabled\n

Warning

The ec4j library used by ktlint does not seem to work with globs starting with ** followed by a chain of multiple directories (for example **/path/to/generated/**/*). But both some/path/to/generated/**/* and **/generated/**/* work fine.

"},{"location":"quick-start/","title":"Quick start","text":"

Follow steps below for a quick start with latest ktlint release.

"},{"location":"quick-start/#step-1-install-with-brew","title":"Step 1: Install with brew","text":"

brew install ktlint\n
See download and verification from GitHub or other package managers for alternative ways of installing ktlint. Or, use one of the integrations like maven and gradle plugins.

"},{"location":"quick-start/#step-2-lint-and-format-your-code","title":"Step 2: Lint and format your code","text":"

All files with extension .kt and .kts in the current directory and below will be scanned. Problems will be fixed automatically when possible. Autocorrect style violations

ktlint --format\n# or\nktlint -F\n
See cli usage for a more extensive description on using ktlint.

"},{"location":"readme/","title":"Build & test documentation on local machine","text":"

The documentation of ktlint is served with mkdocs-material. For full documentation visit mkdocs.org.

To build and test documentation on your local development machine, follow steps below:

"},{"location":"readme/#setup","title":"Setup","text":"
  1. In IntelliJ IDEA
  2. Pull docker image
    $ docker pull squidfunk/mkdocs-material\n
"},{"location":"readme/#build-server","title":"Build server","text":"

The following steps build and host the documentation locally, updating automatically whenever a local file is changed.

  1. Start mkdocs server from root of project (e.g. from same directory where file mkdocs.yml is located)
    docker run --rm -it -p 8000:8000 -v ${PWD}:/docs squidfunk/mkdocs-material\n
  2. Visit page http://0.0.0.0:8000/ in your browser.
  3. Edit the documentation and explicitly save the file. The mkdocs server refreshes its cached and the current page in the browser is automatically refreshed.
"},{"location":"readme/#build-once","title":"Build once","text":"

If you do not want to run a local server, or if you want to inspect the built files, you can run the following command from the project's main directory to build the documentation in the site/ directory.

docker run --rm -it -p 8000:8000 -v ${PWD}:/docs squidfunk/mkdocs-material build\n
"},{"location":"api/badge/","title":"Badge","text":"

If you want to display a badge to show that your project is linted and formatted using 'ktlint than you can add the badge:

Ktlint code style badge
[![ktlint](https://img.shields.io/badge/ktlint%20code--style-%E2%9D%A4-FF4081)](https://pinterest.github.io/ktlint/)\n
"},{"location":"api/custom-integration/","title":"Custom integration","text":""},{"location":"api/custom-integration/#ktlint-rule-engine","title":"Ktlint Rule Engine","text":"

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 =\n  KtLintRuleEngine(\n    ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,\n  )\n
"},{"location":"api/custom-integration/#rule-provider","title":"Rule provider","text":"

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 your own custom rules, or a combination of both. Creating a set of RuleProviders

val KTLINT_API_CONSUMER_RULE_PROVIDERS =\n  setOf(\n    // Can provide custom rules\n    RuleProvider { NoVarRule() },\n    // but also reuse rules from KtLint rulesets\n    RuleProvider { IndentationRule() },\n  )\n

"},{"location":"api/custom-integration/#editor-config-defaults-overrides","title":"Editor config: defaults & overrides","text":"

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 =\n  KtLintRuleEngine(\n    ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,\n    editorConfigOverride = EditorConfigOverride.from(\n      INDENT_STYLE_PROPERTY to IndentConfig.IndentStyle.SPACE,\n      INDENT_SIZE_PROPERTY to 4\n    )\n  )\n

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 =\n  KtLintRuleEngine(\n    ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,\n    editorConfigDefaults = EditorConfigDefaults.load(\n      path = Paths.get(\"/some/path/to/editorconfig/file/or/directory\"),\n      propertyTypes = KTLINT_API_CONSUMER_RULE_PROVIDERS.propertyTypes(),\n    )\n  )\n
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 =\n  KtLintRuleEngine(\n    ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,\n    editorConfigDefaults = EditorConfigDefaults(\n      org.ec4j.core.model.EditorConfig\n        .builder()\n        // .. add relevant properties\n        .build()\n    )\n  )\n
"},{"location":"api/custom-integration/#lint-format","title":"Lint & format","text":"

Once the KtLintRuleEngine has been defined, it is ready to be invoked for code that has to be linted or formatted. 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(\n    File(\"/some/path/to/file\")\n)\n
or a code snippet (set script to true to handle the snippet as Kotlin script): Code from snippet
val code = Code.fromSnippet(\n    \"\"\"\n    val code = \"some-code\"\n    \"\"\".trimIndent()\n)\n

The lint function is invoked with an optional lambda. Once linting is complete, the lambda will be called for each LintError which is found. Invoking lint

ktLintRuleEngine\n    .lint(code) { lintError ->\n        // handle\n    }\n

The format function is invoked with a lambda. The lambda is called for each LintError which is found. If the LintError can be autocorrected, the return value of the lambda instructs the rule whether this specific LintError is to be autocorrected, or not. If the LintError can not be autocorrected, the return result of the lambda is ignored. The formatted code is returned as result of the function.

The new format function allows the API Consumer to decide which LintError is to be autocorrected, or not. This is most interesting for API Consumers that let their user interactively decide per LintError how it has to be handled. For example see the ktlint-intellij-plugin which in 'manual' mode displays all lint violations, which allows the user to decide which LintError is to be autocorrected.

Note

The difference with the legacy version of the format is subtle. It takes two parameters (a LintError and Boolean denoting whether the LintError is corrected), and it does not return a value.

Invoke format (preferred, starting from Ktlint 1.3)
val formattedCode =\n    ktLintRuleEngine\n      .format(code) { lintError ->\n          if (lintError.canBeAutoCorrected) {\n              // Return AutocorrectDecision.ALLOW_AUTOCORRECT to execute the autocorrect of this lintError if this is supported by the rule.\n              // Return AutocorrectDecision.NO_AUTOCORRECT if the LintError should not be corrected even if is supported by the rule.\n          } else {\n              // In case the LintError can not be autocorrected, the return value of the lambda will be ignored.\n              // For clarity reasons it is advised to return AutocorrectDecision.NO_AUTOCORRECT in case the LintError can not be autocorrected.\n              AutocorrectDecision.NO_AUTOCORRECT\n          }\n      }\n

Warning

Rules need to implement the interface RuleAutocorrectApproveHandler in order to let the API Consumer decide whether a LintError is to be autocorrected, or not. This interface is implemented for all rules provided via the Ktlint project starting from version 1.3. However, external rulesets may not have implemented this interface on their rulesets though. Contact the maintainer of such a ruleset to implement this interface.

The (legacy) format function is invoked with an optional lambda. Once formatting is complete, the lambda will be called for each LintError which is found. The (legacy) format function fixes all LintErrors for which an autocorrect is available. The formatted code is returned as result of the function.

Invoke format (deprecated as of Ktlint 1.3, will be removed in Ktlint 2.0)
// Up until Ktlint 1.2.1 the format was invoked with a lambda having two parameters and not returning a result. This function will be removed in Ktlint 2.0 \nval formattedCode =\n    ktLintRuleEngine\n        .format(code) { lintError, corrected ->\n            // handle\n        }\n
"},{"location":"api/custom-integration/#rule-ruleautocorrectapprovehandler","title":"Rule & RuleAutocorrectApproveHandler","text":"

Note

Providers of custom rules are strongly encouraged to implement RuleAutocorrectApproveHandler interface as described below. The ktlint-intellij-plugin, which will be updated soon after the 1.3 release of Ktlint, make use of this new functionality. If your ruleset is used by users of the plugin, it is very likely that they want to be able to autocorrect individual LintErrors or to format a block of code (e.g. a selection) in a file. This functionality will only be available for rules that have implemented this interface.

In Ktlint 1.3 the RuleAutocorrectApproveHandler interface is added. This interface adds the ability that the API Consumer decides per LintError whether it needs to autocorrected, or not. In Ktlint 2.0 the methods beforeVisitChildNodes and afterVisitChildNodes of the Rule class will be replaced with the new versions which are now added to the RuleAutocorrectApproveHandler interface as is shown below (the signature for afterVisitChildNodes is changed similarly):

Deprecated signature in `Rule` class
public open fun beforeVisitChildNodes(\n    node: ASTNode,\n    autoCorrect: Boolean,\n    emit: (\n        offset: Int,\n        errorMessage: String,\n        canBeAutoCorrected: Boolean\n    ) -> Unit,\n)  \n
New signature in `RuleAutocorrectApproveHandler` interface
public fun beforeVisitChildNodes(\n    node: ASTNode,\n    emit: (\n        offset: Int,\n        errorMessage: String,\n        canBeAutoCorrected: Boolean\n    ) -> AutocorrectDecision,\n)\n

The autoCorrect parameter is no longer passed to the method. Instead, the emit lambda now returns the value AutocorrectDecision.ALLOW_AUTOCORRECT or AutocorrectDecision.NO_AUTOCORRECT.

In case a LintError is detected, and can be autocorrected, the LintError can be processed as shown below:

emit(node.startOffset, \"some detail message\", true)\n   .ifAutocorrectAllowed {\n       // Autocorrect the LintError\n   }\n

In case the LintError can not be autocorrected, if suffices to emit the violation only:

emit(node.startOffset, \"some detail message\", false)\n

"},{"location":"api/custom-integration/#logging","title":"Logging","text":"

Ktlint uses the io.github.oshai: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.

"},{"location":"api/custom-reporter/","title":"Custom reporter","text":""},{"location":"api/custom-reporter/#build-a-custom-reporter","title":"Build a custom reporter","text":"

Take a look at ktlint-cli-reporter-plain.

In short, all you need to do is to implement a ReporterV2 and make it available by registering a custom ReporterProviderV2 using META-INF/services/com.pinterest.ktlint.cli.reporter.core.api.ReporterProviderV2. Pack all of that into a JAR and you're done.

To load a custom (3rd party) reporter use ktlint --reporter=name,artifact=/path/to/custom-ktlint-reporter.jar (see ktlint --help for more).

"},{"location":"api/custom-reporter/#third-party-reporters","title":"Third party reporters","text":"

Known third-party reporters:

"},{"location":"api/custom-rule-set/","title":"Custom rule set","text":"

Tip

See Writing your first ktlint rule by Niklas Baudy.

In a nutshell: a \"rule set\" is a JAR containing one or more Rules. ktlint is relying on the ServiceLoader to discover all available \"RuleSet\"s on the classpath. As a ruleset author, all you need to do is to include a META-INF/services/RuleSetProviderV3 file containing a fully qualified name of your RuleSetProviderV3 implementation.

"},{"location":"api/custom-rule-set/#ktlint-ruleset-template","title":"ktlint-ruleset-template","text":"

A complete sample project (with tests and build files) is included in this repo under the ktlint-ruleset-template directory (make sure to check NoVarRuleTest as it contains some useful information).

Building the ktlint-ruleset-template
$ cd ktlint-ruleset-template/\n$ ../gradlew build\n
Provide code sample that violates rule `custom:no-var
$ echo 'var v = 0' > test.kt\n
Running the ktlint-ruleset-template
$ ktlint -R build/libs/ktlint-ruleset-template.jar --log-level=debug --relative test.kt\n\n18:13:21.026 [main] DEBUG com.pinterest.ktlint.internal.RuleSetsLoader - JAR ruleset provided with path \"/../ktlint/ktlint-ruleset-template/build/libs/ktlint-ruleset-template.jar\"\n18:13:21.241 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"baseline\" id.\n18:13:21.241 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"checkstyle\" id.\n18:13:21.241 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"json\" id.\n18:13:21.242 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"html\" id.\n18:13:21.242 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"plain\" id.\n18:13:21.242 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"sarif\" id.\n18:13:21.242 [main] DEBUG com.pinterest.ktlint.Main - Initializing \"plain\" reporter with {verbose=false, color=false, color_name=DARK_GRAY}\n[DEBUG] Rule with id 'standard:max-line-length' should run after the rule with id 'trailing-comma'. However, the latter rule is not loaded and is allowed to be ignored. For best results, it is advised load the rule.\n[DEBUG] Rules will be executed in order below (unless disabled):\n           - standard:filename, \n           - standard:final-newline, \n           - standard:chain-wrapping, \n           - standard:colon-spacing, \n           - standard:comma-spacing, \n           - standard:comment-spacing, \n           - standard:curly-spacing, \n           - standard:dot-spacing, \n           - standard:import-ordering, \n           - standard:keyword-spacing, \n           - standard:modifier-order, \n           - standard:no-blank-line-before-rbrace, \n           - standard:no-consecutive-blank-lines, \n           - standard:no-empty-class-body, \n           - standard:no-line-break-after-else, \n           - standard:no-line-break-before-assignment, \n           - standard:no-multi-spaces, \n           - standard:no-semi, \n           - standard:no-trailing-spaces, \n           - standard:no-unit-return, \n           - standard:no-unused-imports, \n           - standard:no-wildcard-imports, \n           - standard:op-spacing, \n           - standard:parameter-list-wrapping, \n           - standard:paren-spacing, \n           - standard:range-spacing, \n           - standard:string-template, \n           - custom:no-var, \n           - standard:indent, \n           - standard:max-line-length\n`text test.kt:1:1: Unexpected var, use val instead (cannot be auto-corrected)`\n18:13:21.893 [main] DEBUG com.pinterest.ktlint.Main - 872ms / 1 file(s) / 1 error(s)\n

Tip

Multiple custom rule sets can be loaded at the same time.

"},{"location":"api/custom-rule-set/#abstract-syntax-tree-ast","title":"Abstract Syntax Tree (AST)","text":"

While writing/debugging Rules it's often helpful to inspect the Abstract Syntax Tree (AST) of the code snippet that is to be linted / formatted. The Jetbrain PsiViewer plugin for IntelliJ IDEA is a convenient tool to inspect code as shown below:

"},{"location":"api/overview/","title":"Overview","text":"

Ktlint has an open API with which you can integrate.

The diagram below show the internal module structure of KtLint.

The Ktlint Rule Engine is by far the most important module. It is responsible for executing the linting and formatting of the source code. The Rule Engine itself does not contain any rules. Rules are provided by API Consumers.

The Ktlint CLI is an API Consumer of the Ktlint Rule Engine. Together with the Ktlint Ruleset Standard and the Ktlint Reporter modules the CLI offers a standalone tool which can easily be run from the commandline. Also, the Ktlint CLI can easily be used with custom rulesets and/or reporters.

The Ktlint Ruleset Core module contains the logic which is required by each API Consumer of the Ktlint Rule Engine, the Ktlint Ruleset Standard and custom rulesets.

The module Ktlint Test provide functionalities like assertThatRule which is used to write unit tests in a fluent AssertJ look-a-like style and can also be used for testing of custom rules.

The Ktlint logger module provides functionality for writing log messages.

"},{"location":"contributing/","title":"Index","text":""},{"location":"contributing/#contributing-guidelines","title":"Contributing guidelines","text":""},{"location":"contributing/code-of-conduct/","title":"Code of conduct","text":"

At Pinterest, we work hard to ensure that our work environment is welcoming and inclusive to as many people as possible. We are committed to creating this environment for everyone involved in our open source projects as well. We welcome all participants regardless of ability, age, ethnicity, identified gender, religion (or lack there of), sexual orientation and socioeconomic status.

This code of conduct details our expectations for upholding these values.

"},{"location":"contributing/code-of-conduct/#good-behavior","title":"Good behavior","text":"

We expect members of our community to exhibit good behavior including (but of course not limited to):

"},{"location":"contributing/code-of-conduct/#unacceptable-behavior","title":"Unacceptable behavior","text":"

Some examples of unacceptable behavior (again, this is not an exhaustive list):

"},{"location":"contributing/code-of-conduct/#recourse","title":"Recourse","text":"

If you are witness to or the target of unacceptable behavior, it should be reported to Pinterest at opensource-policy@pinterest.com. All reporters will be kept confidential and an appropriate response for each incident will be evaluated.

If the maintainers do not uphold and enforce this code of conduct in good faith, community leadership will hold them accountable.

"},{"location":"contributing/guidelines/","title":"Guidelines","text":"

First off, thanks for taking the time to contribute! This guide will answer some common questions about how this project works.

While this is a Pinterest open source project, we welcome contributions from everyone. Regular outside contributors can become project maintainers.

"},{"location":"contributing/guidelines/#help","title":"Help","text":"

If you're having trouble using this project, please start by reading all documentation and searching for solutions in the existing open and closed issues.

"},{"location":"contributing/guidelines/#security","title":"Security","text":"

If you've found a security issue in one of our open source projects, please report it at Bugcrowd; you may even make some money!

"},{"location":"contributing/guidelines/#code-of-conduct","title":"Code of Conduct","text":"

Please be sure to read and understand our code of conduct. We work hard to ensure that our projects are welcoming and inclusive to as many people as possible.

"},{"location":"contributing/guidelines/#reporting-issues","title":"Reporting Issues","text":"

If you have a bug report, please provide as much information as possible so that we can help you out:

"},{"location":"contributing/guidelines/#making-changes","title":"Making Changes","text":"

Tip

ktlint only provides rules that enforce the Kotlin coding conventions or Android Kotlin style guide. If your change is more opinionated than please file an issue first so that it can be discussed amongst the community. Rules which are too opinionated might be better published as a custom rule set.

  1. Fork this repository to your own account
  2. Make your changes and verify that tests pass
  3. Commit your work and push to a new branch on your fork
  4. Submit a pull request
  5. Participate in the code review process by responding to feedback

Once there is agreement that the code is in good shape, one of the project's maintainers will merge your contribution.

To increase the chances that your pull request will be accepted:

New rules have to implement the Rule.Experimental interface so that the rule will only be run for user who have opted in to use experimental rules. Once the rule is stable, the marker interface Rule.Experimental can be removed.

"},{"location":"contributing/guidelines/#updating-dependencies","title":"Updating dependencies","text":"

This project has enabled Gradle dependencies verification. On adding/updating any dependency, ensure that you've added dependency provided checksum/signature to gradle/verification-metadata.xml file.

"},{"location":"contributing/guidelines/#using-kotlin-development-versions","title":"Using kotlin development versions","text":"

Add following flag - -PkotlinDev to enable kotlin development version.

"},{"location":"contributing/guidelines/#license","title":"License","text":"

By contributing to this project, you agree that your contributions will be licensed under its license.

"},{"location":"contributing/overview/","title":"Overview","text":"

Important

Make sure to read the Contributing guideline and the code of conduct first.

"},{"location":"contributing/overview/#development","title":"Development","text":"

Development starts with cloning and building the project on your local machine:

git clone https://github.com/pinterest/ktlint && cd ktlint\n./gradlew tasks # shows how to build, test, run, etc. project\n

Tip

To open and run ktlint in Intellij IDEA:

"},{"location":"install/cli/","title":"Command line","text":"

Command Line usage

If you don't plan to use ktlint's command line interface then you can skip this section.

"},{"location":"install/cli/#download-and-verification","title":"Download and verification","text":""},{"location":"install/cli/#download-manually-from-github","title":"Download manually from github","text":"

All releases of ktlint can be downloaded from the releases page.

"},{"location":"install/cli/#download-using-curl","title":"Download using curl","text":"

A particular version of ktlint can be downloaded with next command which also changes the file to an executable in directory /usr/local/bin:

Download
curl -sSLO https://github.com/pinterest/ktlint/releases/download/1.4.0/ktlint && chmod a+x ktlint && sudo mv ktlint /usr/local/bin/\n

Curl not installed or behind proxy

If you don't have curl installed - replace curl -sL with wget -qO-. If you are behind a proxy see - curl / wget manpage. Usually simple:

http_proxy=http://proxy-server:port https_proxy=http://proxy-server:port curl -sL ...\n

"},{"location":"install/cli/#verification-of-download","title":"Verification of download","text":"

ktlint.asc contains PGP signature which you can verify with:

Verify releases 0.32.0 and above
curl -sS https://keybase.io/ktlint/pgp_keys.asc | gpg --import && gpg --verify ktlint.asc\n
Verify releases up through 0.31.0
curl -sS https://keybase.io/shyiko/pgp_keys.asc | gpg --import && gpg --verify ktlint.asc\n
"},{"location":"install/cli/#package-managers","title":"Package managers","text":"

ktlint can be installed via several OS specific package managers.

Install with brew on macOS or Homebrew on Linux

brew install ktlint\n

Install with MacPorts

port install ktlint\n

On Arch Linux install package ktlint AUR.

"},{"location":"install/cli/#command-line-usage","title":"Command line usage","text":""},{"location":"install/cli/#rule-sets","title":"Rule set(s)","text":"

When no arguments are specified, the style of all Kotlin files (ending with '.kt' or '.kts') inside the current dir (recursively) are validated with the rules from the standard ruleset. Hidden folders will be skipped.

Default validation with standard ruleset
ktlint\n

Note

The experimental rules in the standard rule set will only be run when .editorconfig property ktlint_experimental = enabled is set.

To validate with a custom ruleset run command below:

Validation with standard and a custom ruleset
ktlint --ruleset=/path/to/custom-ruleset.jar\n# or\nktlint -R /path/to/custom-ruleset.jar\n

Note

If the custom rule set contains rules that are marked as experimental, those rule will only be run when .editorconfig property ktlint_experimental = enabled is set.

"},{"location":"install/cli/#format-autocorrect","title":"Format (autocorrect)","text":"

Most style violations can be corrected automatically. Errors that can not be corrected, are printed to stderr.

Autocorrect style violations
ktlint --format\n# or\nktlint -F\n
"},{"location":"install/cli/#globs","title":"Globs","text":"

Globs can be used to specify more exactly what files and directories are to be validated. ktlint uses the .gitignore pattern style syntax for globs. Globs are processed from left to right. Prepend a glob with ! to negate it. Hidden folders will be skipped.

Check only certain locations starting from the current directory
# Check all '.kt' files in 'src/' directory, but ignore files ending with 'Test.kt':\nktlint 'src/**/*.kt' '!src/**/*Test.kt'\n\n# Check all '.kt' files in 'src/' directory, but ignore 'generated' directory and its subdirectories:\nktlint 'src/**/*.kt' '!src/**/generated/**'\n
"},{"location":"install/cli/#violation-reporting","title":"Violation reporting","text":"

ktlint supports different type of reporters for lint violations. When not specified the plain reporter is used. Optionally the plain reporter can group the violations per file.

Style violation grouped by file
$ ktlint --reporter=plain?group_by_file\n

When using ktlint on an existing project, the number of violations can be huge. To get more insights in which rules are causing the most violations, the plain-summary reporter can be used. Style violations counted per rule

$ ktlint --reporter=plain-summary\n

Other built-in reporters are: json, sarif, checkstyle, and html

Style violations can be written to an output file which is convenient when multiple reporters are specified. In example below, the plain reporter is used to write to the console while the checkstyle reports is written to a file:

Multiple reporters
ktlint --reporter=plain --reporter=checkstyle,output=ktlint-report-in-checkstyle-format.xml\n

If resolving all existing errors in a project is unwanted, it is possible to create a baseline and in following invocations compare violations against this baseline. Violations that are registered in the baseline, will be ignored silently. Remove the baseline file in case you want to reset it.

Check against a baseline file
ktlint --baseline=ktlint-baseline.xml # Baseline is created when not existing\n
"},{"location":"install/cli/#logging","title":"Logging","text":"

Logging information is written to stdout. The amount of logging can be influenced by setting the minimal log level using option --log-level or -l to one of values trace, debug, info, warn, error, or none to suppress all logging.

By default, the info log level is used meaning that all log lines at level info, warn and error are shown while suppressing log lines at level debug or trace.

"},{"location":"install/cli/#rule-configuration-editorconfig","title":"Rule configuration (.editorconfig)","text":"

Some rules can be tweaked via the editorconfig file.

A scaffold of the .editorconfig file can be generated with command below. Note: that the generated file only contains configuration settings which are actively used by the rules which are loaded:

Generate .editorconfig
# Specify the code style(ktlint_official, intellij_idea or android_studio) to be used when generating the .editorconfig\nktlint generateEditorConfig ktlint_official\n# or\nktlint --ruleset=/path/to/custom-ruleset.jar generateEditorConfig android_studio\n

Normally the .editorconfig file is located in the root of your project directory. In case the file is located in a sub folder of the project, the settings of that file only applies to that subdirectory and its folders (recursively). Ktlint automatically detects and reads all .editorconfig files in your project.

Use command below, to specify a default editorconfig. In case a property is not defined in any .editorconfig file on the path to the file, the value from the default file is used. The path may point to any valid file or directory. The path can be relative or absolute. Depending on your OS, the \"~\" at the beginning of a path is replaced by the user home directory.

Override '.editorconfig'
ktlint --editorconfig=/path/to/.editorconfig\n

Overrides '.editorconfig' in project directory\" in KtLint 0.46 and older

When specifying this option using ktlint 0.46 or older, all .editorconfig files in the project directory are being ignored. Starting from KtLint 0.47 the properties in this file are used as fallback.

"},{"location":"install/cli/#stdin-stdout","title":"Stdin && stdout","text":"

With command below, the input is read from stdin and the violations are printed to stderr. Logging is written to stdout.

Lint from stdin
ktlint --stdin\n

When combined with the --format option, the formatted code is written to stdout and the violations are printed to stderr:

Format from stdin and write to stdout
ktlint --stdin -F\n

Suppress logging and error output

Logging output printed to stdout can be suppressed by setting --log-level=none (see logging). Output printed to stderr can be suppressed in different ways. To ignore all error output, add 2> /dev/null to the end of the command line. Otherwise, specify a reporter to write the error output to a file.

If input from stdin represents the contents of a file, the file path can be supplied with stdin-path. This path is made available for rules to use, the --format option will not modify this file.

file path from stdin-path
ktlint --stdin --stdin-path /path/to/file/Foo.kt\n
"},{"location":"install/cli/#git-hooks","title":"Git hooks","text":"

Predefined git hooks can be installed, to automatically validate lint errors before commit or push.

Install git pre-commit hook
ktlint installGitPreCommitHook\n
Install git pre-push hook
ktlint installGitPrePushHook\n
"},{"location":"install/cli/#miscellaneous-flags-and-commands","title":"Miscellaneous flags and commands","text":"

--color and --color-name=<colorName>: Make output colorful and optionally set the color name to use.

-h or --help: Prints help information.

--limit=<limit>: Maximum number of errors to show (default: show all)

--relative: Print files relative to the working directory (e.g. dir/file.kt instead of /home/user/project/dir/file.kt)

--patterns-from-stdin[=<delimiter>]: Reads additional patterns from stdin, where the patterns are separated by <delimiter>. If =<delimiter> is omitted, newline is used as fallback delimiter. If an empty string is given, the NUL byte is used as delimiter instead. If this option is given, then the default patterns are disabled. Options --stdin and --patterns-from-stdin are mutually exclusive, only one of them can be given at a time.

-V or --version: Prints version information and exit.

"},{"location":"install/cli/#microsoft-windows-users","title":"Microsoft Windows users","text":"

Microsoft Windows is not able to run the ktlint command directly. Ktlint can be run in following ways on Microsoft Windows:

  1. Use the ktlint.bat batch file provided as part of the release. Add the batch file to your %PATH% environment variable for easy access
  2. Run ktlint using Git Bash
  3. Run as java -jar ktlint
"},{"location":"install/integrations/","title":"Integrations","text":""},{"location":"install/integrations/#maven-integration","title":"Maven integration","text":"

By adding the plugin definition below to the <plugins> section in the pom.xml:

See cli usage for arguments that can be supplied to ktlint.

Adding plugin to pom.xml
...\n<plugin>\n    <groupId>org.apache.maven.plugins</groupId>\n    <artifactId>maven-antrun-plugin</artifactId>\n    <version>3.1.0</version>\n    <executions>\n        <execution>\n            <id>ktlint</id>\n            <phase>verify</phase>\n            <configuration>\n            <target name=\"ktlint\">\n                <java taskname=\"ktlint\" dir=\"${basedir}\" fork=\"true\" failonerror=\"true\"\n                    classpathref=\"maven.plugin.classpath\" classname=\"com.pinterest.ktlint.Main\">\n                  <!-- Note: the JVM arg below is only required when running ktlint with Java 16+ in format mode.\n                  <jvmarg value=\"--add-opens=java.base/java.lang=ALL-UNNAMED\"/>\n                  -->\n                  <!-- see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information -->\n                  <arg value=\"src/**/*.kt\"/>\n                </java>\n            </target>\n            </configuration>\n            <goals>\n                <goal>run</goal>\n            </goals>\n        </execution>\n        <execution>\n            <id>ktlint-format</id>\n            <configuration>\n            <target name=\"ktlint\">\n                <java taskname=\"ktlint\" dir=\"${basedir}\" fork=\"true\" failonerror=\"true\"\n                    classpathref=\"maven.plugin.classpath\" classname=\"com.pinterest.ktlint.Main\">\n                    <!-- Note: the JVM args below is only required when running ktlint with Java 16+ in format mode -->\n                    <jvmarg value=\"--add-opens=java.base/java.lang=ALL-UNNAMED\"/>\n                    <!-- see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information -->\n                    <arg value=\"-F\"/>\n                    <arg value=\"src/**/*.kt\"/>\n                </java>\n            </target>\n            </configuration>\n            <goals>\n                <goal>run</goal>\n            </goals>\n        </execution>\n    </executions>\n    <dependencies>\n        <dependency>\n            <groupId>com.pinterest.ktlint</groupId>\n            <artifactId>ktlint-cli</artifactId>\n            <version>1.4.0</version>\n        </dependency>\n        <!-- additional 3rd party ruleset(s) can be specified here -->\n    </dependencies>\n</plugin>\n...\n

Tip

If you want ktlint to run before code compilation takes place - change <phase>verify</phase> to <phase>validate</phase> (see Maven Build Lifecycle for more).

ktlint-maven-plugin

You might be interested to use the dedicated gantsign/ktlint-maven-plugin.

"},{"location":"install/integrations/#gradle-integration","title":"Gradle integration","text":""},{"location":"install/integrations/#jlleitschuhktlint-gradle","title":"jlleitschuh/ktlint-gradle","text":"

The jlleitschuh/ktlint-gradle Gradle plugin automatically creates check and format tasks for project Kotlin sources. It supports different kotlin plugins and Gradle build caching.

"},{"location":"install/integrations/#jeremymailenkotlinter-gradle","title":"jeremymailen/kotlinter-gradle","text":"

The jeremymailen/kotlinter-gradle Gradle plugin features incremental build support, file reports, and *.kts source support.

"},{"location":"install/integrations/#diffplugspotless","title":"diffplug/spotless","text":"

The diffplug/spotless Gradle plugin is a general-purpose formatting plugin which amongst many others also supports ktlint.

"},{"location":"install/integrations/#autostyleautostyle","title":"autostyle/autostyle","text":"

The autostyle/autostyle Gradle plugin is a general-purpose formatting plugin which amongst others also supports ktlint.

"},{"location":"install/integrations/#custom-gradle-integration","title":"Custom Gradle integration","text":""},{"location":"install/integrations/#custom-gradle-integration-with-groovy","title":"Custom Gradle integration with Groovy","text":"

Warning

It is recommended to use one of the Gradle plugins mentioned before.

The configuration below, defines following task:

build.gradle
// kotlin-gradle-plugin must be applied for configuration below to work\n// (see https://kotlinlang.org/docs/reference/using-gradle.html)\n\nplugins {\n    id 'java'\n}\n\nrepositories {\n    mavenCentral()\n}\n\nconfigurations {\n    ktlint\n}\n\ndependencies {\n    ktlint(\"com.pinterest.ktlint:ktlint-cli:1.4.0\") {\n        attributes {\n            attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))\n        }\n    }\n    // additional 3rd party ruleset(s) can be specified here\n    // just add them to the classpath (e.g. ktlint 'groupId:artifactId:version') and \n    // ktlint will pick them up\n}\n\ntasks.register(\"ktlintCheck\", JavaExec) {\n    group = \"verification\"\n    description = \"Check Kotlin code style.\"\n    classpath = configurations.ktlint\n    mainClass = \"com.pinterest.ktlint.Main\"\n    // see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information\n    args \"src/**/*.kt\", \"**.kts\", \"!**/build/**\"\n}\n\ntasks.named(\"check\") {\n    dependsOn tasks.named(\"ktlintCheck\")\n}\n\ntasks.register(\"ktlintFormat\", JavaExec) {\n    group = \"formatting\"\n    description = \"Fix Kotlin code style deviations.\"\n    classpath = configurations.ktlint\n    mainClass = \"com.pinterest.ktlint.Main\"\n    jvmArgs \"--add-opens=java.base/java.lang=ALL-UNNAMED\"\n    // see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information\n    args \"-F\", \"src/**/*.kt\", \"**.kts\", \"!**/build/**\"\n}\n

See Making your Gradle tasks incremental by Niklas Baudy on how to make tasks above incremental.

"},{"location":"install/integrations/#custom-gradle-integration-with-kotlin-dsl","title":"Custom Gradle integration with Kotlin DSL","text":"

Warning

It is recommended to use one of the Gradle plugins mentioned before.

The configuration below, defines following task:

build.gradle.kts
val ktlint by configurations.creating\n\ndependencies {\n    ktlint(\"com.pinterest.ktlint:ktlint-cli:1.4.0\") {\n        attributes {\n            attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))\n        }\n    }\n    // ktlint(project(\":custom-ktlint-ruleset\")) // in case of custom ruleset\n}\n\nval ktlintCheck by tasks.registering(JavaExec::class) {\n    group = LifecycleBasePlugin.VERIFICATION_GROUP\n    description = \"Check Kotlin code style\"\n    classpath = ktlint\n    mainClass.set(\"com.pinterest.ktlint.Main\")\n    // see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information\n    args(\n        \"**/src/**/*.kt\",\n        \"**.kts\",\n        \"!**/build/**\",\n    )\n}\n\ntasks.check {\n    dependsOn(ktlintCheck)\n}\n\ntasks.register<JavaExec>(\"ktlintFormat\") {\n    group = LifecycleBasePlugin.VERIFICATION_GROUP\n    description = \"Check Kotlin code style and format\"\n    classpath = ktlint\n    mainClass.set(\"com.pinterest.ktlint.Main\")\n    jvmArgs(\"--add-opens=java.base/java.lang=ALL-UNNAMED\")\n    // see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information\n    args(\n        \"-F\",\n        \"**/src/**/*.kt\",\n        \"**.kts\",\n        \"!**/build/**\",\n    )\n}\n
"},{"location":"install/integrations/#gnu-emacs-integration","title":"GNU Emacs integration","text":"

See whirm/flycheck-kotlin.

"},{"location":"install/integrations/#vim-integration","title":"Vim integration","text":"

See w0rp/ale.

"},{"location":"install/integrations/#mega-linter-integration","title":"Mega-Linter integration","text":"

The Mega-Linter integrates 70+ linters in a single tool for CI, including ktlint activated out of the box

"},{"location":"install/integrations/#tca-integration","title":"TCA integration","text":"

Tencent Cloud Code Analysis (TCA for short, code-named CodeDog inside the company early) is a comprehensive platform for code analysis and issue tracking. TCA consist of three components, server, web and client. It integrates of a number of self-developed tools, and also supports dynamic integration of code analysis tools in various programming languages.

"},{"location":"install/integrations/#other-integration","title":"Other integration","text":"

Do you know any other integration with ktlint then please create a PR to add this integration to our documentation.

"},{"location":"install/setup/","title":"Recommended setup","text":"

Ktlint can be installed in a lot of different ways. It depends on your situation what works best for you.

As maintainer of Ktlint, I advise setup below to maximize your productivity, and get feedback early according to the failing fast principle.

  1. ktlint-intellij-plugin for direct feedback while coding
  2. Git pre-commit hook for feedback when committing
  3. Build pipeline as last defence
"},{"location":"install/setup/#ktlint-intellij-plugin-for-direct-feedback-while-coding","title":"ktlint-intellij-plugin for direct feedback while coding","text":"

Tip

Ensure to install version 0.20.0 (or later) of the Ktlint plugin via the Intellij Plugin Marketplace to get benefits described below.

The ktlint-intellij-plugin gives direct feedback while writing code. The plugin can be used in 'distract free' and 'manual' mode, or be disabled entirely. This is a per-project setting.

In distract free mode, the plugin only shows the violations which need to be manually corrected. Ktlint formatting will be applied automatically after apply Intellij IDEA format, or on save of the file. This works bests for projects for which the .editorconfig already has been set up properly for the project.

Note that image above also shows a warning that 'Ktlint found 5 violations which can be autocorrected'. Reformatting the file, or simply save the file, results in:

In 'manual' mode, or in 'distract free' mode after selecting 'Show all Ktlint violations in file', each individual violation is shown as error. This allows for suppressing errors that can be autocorrected, but for which this is unwanted.

Violations reported by ktlint can be suppressed by adding a @Suppress annotation via the quick fix:

As of Ktlint 1.1.0 the maintainer of Ktlint has joined the ktlint-intellij-plugin project to ensure that the plugin stays up to date with releases of ktlint and releases of Intellij IDEA.

The ktlint-intellij-plugin can be installed as plugin in Intellij IDEA.

"},{"location":"install/setup/#git-pre-commit-hook-for-feedback-when-committing","title":"Git pre-commit hook for feedback when committing","text":"

The git pre-commit hook, protects against committing code containing lint violations. From the perspective of code reviewing it is important that the code is already formatted in the style of the project. This is especially valuable after refactorings (for example search and replace) have been applied on files that are not opened in the editor and as of that might not have been updated by the ktlint-intellij-plugin.

Ktlint CLI can generate a pre-commit hook, or you can find it here.

"},{"location":"install/setup/#build-pipeline-as-last-defence","title":"Build pipeline as last defence","text":"

As last defence, to ensure that the code base does not contain lint violations, ktlint-cli is run in the (local and remote) build pipeline (see integrations.

For example, in my maven projects I have bound the ktlint (linting) task to the maven compile lifecycle. If after compile a lint violation is found the build is failed. This circumvents that developers disable running of the git hooks on their local machine. And in case that the code was not build locally, the remote build pipeline fails as last resort.

"},{"location":"install/snapshot-build/","title":"Snapshot build","text":""},{"location":"install/snapshot-build/#access-to-the-latest-master-snapshot","title":"Access to the latest master snapshot","text":"

Whenever a commit is added to the master branch a snapshot build is automatically uploaded to Sonatype's snapshots repository. If you are eager to try upcoming changes (that might or might not be included in the next stable release) you can do so by changing version of ktlint to <latest-version>-SNAPSHOT + adding a repo:

"},{"location":"install/snapshot-build/#maven","title":"Maven","text":"
...\n<repository>\n    <id>sonatype-snapshots</id>\n    <url>https://oss.sonatype.org/content/repositories/snapshots</url>\n    <snapshots>\n        <enabled>true</enabled>\n    </snapshots>\n    <releases>\n        <enabled>false</enabled>\n    </releases>\n</repository>\n...\n
"},{"location":"install/snapshot-build/#gradle","title":"Gradle","text":"
repositories {\n  maven {\n    url \"https://oss.sonatype.org/content/repositories/snapshots\"\n  }\n}\n
"},{"location":"install/snapshot-build/#kotlin-development-version-snapshot","title":"Kotlin development version snapshot","text":"

Additionally, project publishes snapshots build against latest kotlin development version. To use them, change version of ktlint to <latest-version>-kotlin-dev-SNAPSHOT.

"},{"location":"rules/","title":"Index","text":"

= Rules

"},{"location":"rules/code-styles/","title":"Code styles","text":"

Starting from version 1.0, ktlint_official is the default code style. If you want to revert to another code style, then set the .editorconfig property ktlint_code_style.

[*.{kt,kts}]\nktlint_code_style = intellij_idea # or android_studio or ktlint_official (default)\n

The ktlint_official code style combines the best elements from the Kotlin Coding conventions and Android's Kotlin styleguide. This code style also provides additional formatting on topics which are not (explicitly) mentioned in those conventions and style guide.

Note

Be aware that this code style in some cases formats code in a way which is not accepted by the default code formatters in IntelliJ IDEA and Android Studio. The formatters of those editors produce nicely formatted code in the vast majority of cases. But in a number of edge cases, the formatting contains bugs which are waiting to be fixed for several years. The new code style formats code in a way which is compatible with the default formatting of the editors whenever possible. When using this codestyle, it is best to disable (e.g. not use) code formatting in the editor.

"},{"location":"rules/configuration-intellij-idea/","title":"Intellij IDEA configuration","text":"

ktlint strives to prevent code formatting conflicts with IntelliJ IDEA / Android Studio as much as possible. In some cases, ktlint deliberately deviates from IDEA formatting.

"},{"location":"rules/configuration-intellij-idea/#preventing-conflicts","title":"Preventing conflicts","text":"

Many conflicts can be prevented by setting following .editorconfig settings:

root = true\n\n[*]\ninsert_final_newline = true\n\n[{*.kt,*.kts}]\nij_kotlin_code_style_defaults = KOTLIN_OFFICIAL\n\n#  Disable wildcard imports entirely\nij_kotlin_name_count_to_use_star_import = 2147483647\nij_kotlin_name_count_to_use_star_import_for_members = 2147483647\nij_kotlin_packages_to_use_import_on_demand = unset\n

Conflicts between ktlint and IDEA formatting can also be resolved by using the ktlint-intellij-plugin (or install via Intellij IDEA plugin marketplace) in distract free mode. In this mode, the plugin formats your code with ktlint while you're editing the code.

"},{"location":"rules/configuration-intellij-idea/#cleaning-up-old-xml-configuration-settings","title":"Cleaning up old XML configuration settings","text":"

Projects which have been created with (old)er versions of Intellij IDEA might still contain XML configuration regarding code styling. It is advised to remove the directory .idea/codeStyles whenever it still exists in your project directory.

"},{"location":"rules/configuration-ktlint/","title":"KtLint configuration","text":"

Ktlint uses a limited set of .editorconfig properties for additional configuration. A sensible default value is provided for each property when not explicitly defined. Properties can be overridden, provided they are specified under [*.{kt,kts}]. Ktlint uses some properties defined by .editorconfig, IntelliJ IDEA and custom properties.

Danger

Unfortunately IntelliJ IDEA has an autoformat issue regarding .editorconfig. Due to this error an additional space is added between glob statements, resulting in [*{kt, kts}] instead of [*{kt,kts}]. The .editorconfig library used by ktlint ignores sections after encountering a space in the list. As a result, the rule is not applied on all files as documented in the original ktlint issue.

"},{"location":"rules/configuration-ktlint/#code-style","title":"Code style","text":"

By default, the ktlint_official code style is applied. Alternatively, the code style can be set to intellij_idea or android_studio.

[*.{kt,kts}]\nktlint_code_style = ktlint_official\n
"},{"location":"rules/configuration-ktlint/#disable-rules","title":"Disable rule(s)","text":"

Rule sets and individual rules can be disabled / enabled with a separate property per rule (set).

All rules in a rule set can be enabled or disabled with a rule set property. The name of the rule set property consists of the ktlint_ prefix followed by the rule set id. Examples:

ktlint_standard = disabled # Disable all rules from the `standard` rule set provided by KtLint\nktlint_experimental = enabled # Enable all `experimental` rules from all rule sets provided by KtLint or other rule providers\nktlint_custom-rule-set = enabled # Enable all rules in the `custom-rule-set` rule set (not provided by KtLint)\n

Rules that are marked as experimental will not be run, unless explicitly enabled:

ktlint_experimental = enabled # Enable rules marked as experimental for all rule sets that are enabled\n

An individual rule can be enabled or disabled with a rule property. The name of the rule property consists of the ktlint_ prefix followed by the rule set id followed by a _ and the rule id. Examples:

ktlint_standard_final-newline = disabled # Disables the `final-newline` rule provided by KtLint\nktlint_standard_some-experimental-rule = enabled # Enables the (experimental) `some-experimental-rule` in the `standard` rule set provided by KtLint\nktlint_custom-rule-set_custom-rule = disabled # Disables the `custom-rule` rule in the `custom-rule-set` rule set (not provided by KtLint)\n

Note

The rule properties are applied after applying the rule set properties and take precedence. So if a rule set is disabled but a specific rule of that rule set is enabled, then the rule will be executed.

"},{"location":"rules/configuration-ktlint/#rule-specific-configuration-settings","title":"Rule specific configuration settings","text":"

The configuration settings below are used to configure the behavior of a specific rule. As of that, those settings only take effect when the corresponding rule is enabled. See description of rule for more information about the setting.

Configuration setting Rule ij_kotlin_allow_trailing_comma trailing-comma-on-declaration-site ij_kotlin_allow_trailing_comma_on_call_site trailing-comma-on-call-site ij_kotlin_packages_to_use_import_on_demand no-wildcard-imports indent_size indent indent_style indent insert_final_newline final-newline ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_than chain-method-continuation ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than class-signature ktlint_ignore_back_ticked_identifier max-line-length ktlint_function_naming_ignore_when_annotated_with function-naming ktlint_function_signature_body_expression_wrapping function-signature ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than function-signature max_line_length max-line-length and several other rules"},{"location":"rules/configuration-ktlint/#overriding-editorconfig-properties-for-specific-directories","title":"Overriding Editorconfig properties for specific directories","text":"

You can override properties for specific directories inside your project:

[*.{kt,kts}]\nktlint_standard_import-ordering = disabled\n\n[api/*.{kt,kts}]\nktlint_standard_indent = disabled\n

Note that in example above the import-ordering rule is disabled for all packages including the api sub package. Next to this the indent rule is disabled for the api package and its sub packages.

"},{"location":"rules/dependencies/","title":"Dependencies","text":"

Preferably rules run independent of each other. In some case this is however not feasible. The diagram below shows the dependencies between the rules provided by KtLint.

"},{"location":"rules/experimental/","title":"Experimental rules","text":"

Important

Up and until Ktlint version 0.47, experimental were located in a separate experimental rule set. As of Ktlint version 0.48, each rule set can optionally define experimental rules.

All experimental rules described below are part of the standard rule set of Ktlint. To enable all experimental rules (from all rule sets), set editorconfig property below:

[*.{kt,kts}]\nktlint_experimental=enabled\n
Also see enable/disable specific rules.

"},{"location":"rules/experimental/#blank-line-between-when-conditions","title":"Blank line between when-conditions","text":"

Consistently add or remove blank line between when-conditions in a when-statement. A blank line is only added between when-conditions if the when-statement contains at lease one multiline when-condition. If a when-statement only contains single line when-conditions, then the blank lines between the when-conditions are removed.

Note

Ktlint uses .editorconfig property ij_kotlin_line_break_after_multiline_when_entry but applies it also on single line entries to increase consistency.

Ktlint Disallowed
val foo1 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> \"bar2\"\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = true\nval foo2 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n\n        BAR2 -> {\n            \"bar2\"\n        }\n\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = true\nval foo3 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n\n        // BAR2 comment\n        BAR2 -> \"bar2\"\n\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = false\nval foo4 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> {\n            \"bar2\"\n        }\n        else -> null\n    }\n
// ij_kotlin_line_break_after_multiline_when_entry = true | false (no blank lines in simple when-statement)\nval foo1 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n\n        BAR2 -> \"bar2\"\n\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = true (missing newline after BAR1)\nval foo2 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> {\n            \"bar2\"\n        }\n\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = true (missing newline after BAR1, and BAR2)\nval foo3 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        // BAR2 comment\n        BAR2 -> \"bar2\"\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = false (unexpected newline after BAR2)\nval foo4 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> {\n            \"bar2\"\n        }\n\n        else -> null\n    }\n
Configuration setting ktlint_official intellij_idea android_studio ij_kotlin_line_break_after_multiline_when_entryDespite its name, forces a blank line between single line and multiline when-entries when at least one multiline when-entry is found in the when-statement. true true true

Rule id: standard:blank-line-between-when-conditions

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:blank-line-between-when-conditions\")\n
    Enable rule via .editorconfig
    ktlint_standard_blank-line-between-when-conditions = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_blank-line-between-when-conditions = disabled\n
"},{"location":"rules/experimental/#kdoc","title":"KDoc","text":"

KDoc's should only be used on elements for which KDoc is to be transformed to documentation. Normal block comments should be used in other cases.

!!! note: Access modifiers are ignored. Strictly speaking, one could argue that private declarations should not have a KDoc as no documentation will be generated for it. However, for internal use of developers the KDoc still serves documentation purposes.

Ktlint Disallowed
/** some KDoc */\nclass FooBar(\n    /** some KDoc */\n    val foo: Foo\n) {\n    /**\n     * Some bar KDoc\n     */\n    constructor() : this()\n\n    /** some KDoc */\n    val bar: Bar\n}\n\nenum class Foo {\n    /** some KDoc */\n    BAR\n}\n\n/** some KDoc */\ninterface Foo\n/** some KDoc */\nfun foo()\n/** some KDoc */\nval foo: Foo\n/** some KDoc */\nobject foo: Foo\n/** some KDoc */\ntypealias FooBar = (Foo) -> Bar\n
/**\n * Some dangling Kdoc (e.g. not followed by a declaration)\n */\n\nval foo /** Some KDoc */ = \"foo\"\n\nclass Foo(\n    /** some dangling KDoc inside a parameter list */\n)\n

Rule id: standard:kdoc

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:kdoc\")\n
    Enable rule via .editorconfig
    ktlint_standard_kdoc = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_kdoc = disabled\n
"},{"location":"rules/experimental/#mixed-condition-operators","title":"Mixed condition operators","text":"

Conditions should not use a both && and || operators between operators at the same level. By using parenthesis the expression is to be clarified.

Ktlint Disallowed
val foo = bar1 && (bar2 || bar3) && bar4\n
val foo = bar1 &&\n    bar2 ||\n    bar3\nval foo = bar1 && (bar2 || bar3 && bar4) && bar5\n

Rule id: standard:mixed-condition-operators

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:mixed-condition-operators\")\n
    Enable rule via .editorconfig
    ktlint_standard_mixed-condition-operators = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_mixed-condition-operators = disabled\n
"},{"location":"rules/experimental/#square-brackets-spacing","title":"Square brackets spacing","text":"

Check for spacing around square brackets.

Ktlint Disallowed
val foo1 = bar[1]\nval foo2 =\n   bar[\n       1,\n       2,\n   ]\n\n@Foo(\n    fooBar = [\"foo\", \"bar\"],\n    fooBaz = [\n        \"foo\",\n        \"baz\",\n    ],\n)\nfun foo() {}\n
val foo1 = bar [1]\nval foo2 = bar[ 1]\nval foo3 = bar[1 ]\n

Rule id: standard:square-brackets-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:square-brackets-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_square-brackets-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_square-brackets-spacing = disabled\n
"},{"location":"rules/experimental/#when-entry-bracing","title":"When-entry bracing","text":"

Enforce consistent usages of braces inside the when-statement. All when-entries in the when-statement should use braces around their bodies in case at least one when-entry has a multiline body, or when the body is surrounded by braces.

Braces are helpful for following reasons:

This rule is not incorporated in the Kotlin Coding conventions, nor in the Android Kotlin Styleguide. It is based on similar behavior in enforcing consistent use of braces in if-else statements. As of that the rule is only enabled automatically for code style ktlint_official. It can be enabled explicitly for other code styles.

Ktlint Disallowed
val foo1 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> \"bar2\"\n        else -> null\n    }\n\nval foo2 =\n    when (bar) {\n        BAR1 -> {\n            \"bar1\"\n        }\n        BAR2 -> {\n            \"bar2\"\n        }\n        else -> {\n            null\n        }\n    }\n
val foo3 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> {\n            \"bar2\"\n        }\n        else -> null\n    }\n\nval foo4 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 ->\n            \"bar2\"\n        else -> null\n    }\n

Rule id: standard:when-entry-bracing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:when-entry-bracing\")\n
    Enable rule via .editorconfig
    ktlint_standard_when-entry-bracing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_when-entry-bracing = disabled\n
"},{"location":"rules/standard/","title":"Standard rules","text":""},{"location":"rules/standard/#annotation-formatting","title":"Annotation formatting","text":"

Multiple annotations should be on a separate line than the annotated declaration; annotations with parameters should each be on separate lines; annotations should be followed by a space

Ktlint Disallowed
// A single annotation (without parameters) is allowed on same line as annotated construct\n@FunctionalInterface class FooBar {\n    @JvmField var foo: String\n\n    @Test fun bar() {}\n}\n\n// A class or function parameter may have a single annotation with parameter(s) on the same line\nclass Foo(\n    @Path(\"fooId\") val fooId: String,\n    @NotNull(\"bar\") bar: String,\n)\n\n// Multiple annotations (without parameters) are allowed on the same line\n@Foo @Bar\nclass FooBar {\n    @Foo @Bar\n    var foo: String\n\n    @Foo @Bar\n    fun bar() {}\n}\n\n// An array of annotations (without parameters) is allowed on same line as annotated construct\n@[Foo Bar] class FooBar2 {\n    @[Foo Bar] var foo: String\n\n    @[Foo Bar] fun bar() {}\n}\n
// An annotation with parameter(s) is not allowed on same line as annotated construct\n@Suppress(\"Unused\") class FooBar {\n    @Suppress(\"Unused\") var foo: String\n    @Suppress(\"Unused\") fun bar() {}\n}\n// Multiple annotation on same line as annotated construct are not allowed\n@Foo @Bar class FooBar {\n    @Foo @Bar var foo: String\n    @Foo @Bar fun bar() {}\n}\n

Rule id: standard:annotation

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:annotation\")\n
    Enable rule via .editorconfig
    ktlint_standard_annotation = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_annotation = disabled\n
"},{"location":"rules/standard/#binary-expression-wrapping","title":"Binary expression wrapping","text":"

Wraps binary expression at the operator reference whenever the binary expression does not fit on the line. In case the binary expression is nested, the expression is evaluated from outside to inside. If the left and right hand sides of the binary expression, after wrapping, fit on a single line then the inner binary expressions will not be wrapped. If one or both inner binary expression still do not fit on a single after wrapping of the outer binary expression, then each of those inner binary expressions will be wrapped.

Ktlint Disallowed
fun foo() {\n    // Assume that the last allowed character is\n    // at the X character on the right                       X\n    if ((leftHandSideExpression && rightHandSideExpression) ||\n        (\n            leftHandSideLongExpression &&\n                rightHandSideExpression\n        )\n    ) {\n        // do something\n    }\n}\n
fun foo() {\n    // Assume that the last allowed character is\n    // at the X character on the right                       X\n    if ((leftHandSideExpression && rightHandSideExpression) ||\n        (leftHandSideLongExpression && rightHandSideExpression)\n    ) {\n        // do something\n    }\n}\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:binary-expression-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:binary-expression-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_binary-expression-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_binary-expression-wrapping = disabled\n
"},{"location":"rules/standard/#blank-line-before-declarations","title":"Blank line before declarations","text":"

Requires a blank line before any class or function declaration. No blank line is required between the class signature and the first declaration in the class. In a similar way, a blank line is required before any list of top level or class properties. No blank line is required before local properties or between consecutive properties.

Ktlint Disallowed
const val FOO_1 = \"foo1\"\n\nclass FooBar {\n    val foo2 = \"foo2\"\n    val foo3 = \"foo3\"\n\n    fun bar1() {\n        val foo4 = \"foo4\"\n        val foo5 = \"foo5\"\n    }\n\n    fun bar2() = \"bar\"\n\n    val foo6 = \"foo3\"\n    val foo7 = \"foo4\"\n\n    enum class Foo\n}\n
const val FOO_1 = \"foo1\"\n\nclass FooBar {\n    val foo2 = \"foo2\"\n    val foo3 = \"foo3\"\n    fun bar1() {\n        val foo4 = \"foo4\"\n        val foo5 = \"foo5\"\n    }\n    fun bar2() = \"bar\"\n    val foo6 = \"foo3\"\n    val foo7 = \"foo4\"\n    enum class Foo\n}\n

Rule id: standard:blank-line-before-declaration

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:blank-line-before-declaration\")\n
    Enable rule via .editorconfig
    ktlint_standard_blank-line-before-declaration = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_blank-line-before-declaration = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#block-comment-initial-star-alignment","title":"Block comment initial star alignment","text":"

Lines in a block comment which (exclusive the indentation) start with a * should have this * aligned with the * in the opening of the block comment.

Ktlint Disallowed
/*\n * This comment is formatted well.\n */\n
/*\n      * This comment is not formatted well.\n    */\n

Rule id: standard:block-comment-initial-star-alignment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:block-comment-initial-star-alignment\")\n
    Enable rule via .editorconfig
    ktlint_standard_block-comment-initial-star-alignment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_block-comment-initial-star-alignment = disabled\n
"},{"location":"rules/standard/#chain-method-continuation","title":"Chain method continuation","text":"

In a multiline method chain, the chain operators (. or ?.) have to be aligned with each other.

Multiple chained methods on a single line are allowed as long as the maximum line length, and the maximum number of chain operators are not exceeded. Under certain conditions, it is allowed that the expression before the first and/or the expression after the last chain operator is a multiline expression.

The . in java.class is ignored when wrapping on chain operators.

Warning

A binary expression for which the left and/or right operand consist of a method chain are currently being ignored by this rule. Please reach out, if you can help to determine what the best strategy is to deal with such kind of expressions.

Ktlint Disallowed
val foo1 =\n    listOf(1, 2, 3)\n        .filter { it > 2 }!!\n        .takeIf { it > 2 }\n        .map {\n            it * it\n        }?.map {\n            it * it\n        }\nval foo2 =\n    listOf(1, 2, 3)\n        .filter {\n            it > 2\n        }.map {\n            2 * it\n        }?.map {\n            2 * it\n        }\nval foo3 =\n    foo().bar().map {\n        it.foobar()\n    }\nval foo4 =\n    \"\"\"\n    Some text\n    \"\"\".trimIndent().foo().bar()\n
val foo1 =\n    listOf(1, 2, 3).\n        filter { it > 2 }!!.\n        takeIf { it > 2 }.\n        map {\n            it * it\n        }?.\n        map {\n            it * it\n        }\nval foo2 =\n    listOf(1, 2, 3)\n        .filter {\n            it > 2\n        }\n        .map {\n            2 * it\n        }\n        ?.map {\n            2 * it\n        }\nval foo3 = \n    foo()\n    .bar().map {\n        it.foobar()\n    }\nval foo4 =\n    \"\"\"\n    Some text\n    \"\"\".trimIndent().foo()\n        .bar()\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_thanForce wrapping of chained methods in case an expression contains at least the specified number of chain operators. If a chained method contains nested expressions, the chain operators of the inner expression are not taken into account. Use value unset (default) to disable this setting. 4 4 4 max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:chain-method-continuation

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:chain-method-continuation\")\n
    Enable rule via .editorconfig
    ktlint_standard_chain-method-continuation = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_chain-method-continuation = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#class-signature","title":"Class signature","text":"

Rewrites the class signature to a consistent format respecting the .editorconfig property max_line_length if set. In the ktlint_official code style all class parameters are wrapped by default. Set .editorconfig property ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than to a value greater than 1 to allow classes with a few parameters to be placed on a single line. The other code styles allow an infinite amount of parameters on the same line (as long as the max_line_length is not exceeded) unless .editorconfig property ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than is set explicitly.

Ktlint (ktlint_official) Disallowed (ktlint_official) Ktlint (non ktlint_official) Disallowed (non ktlint_official)
// Assume that max_line_length is not exceeded when written as single line\nclass Foo0\n\nclass Foo1(\n    a: Any,\n)\n\nclass Foo2(\n    a: Any,\n    b: Any,\n)\n\nclass Foo3(\n    @Foo a: Any,\n    b: Any,\n    c: Any,\n)\n\nclass Foo4(\n    a: Any,\n    b: Any,\n    c: Any,\n) : FooBar(a, c)\n\nclass Foo5 :\n    FooBar(\n        \"bar1\",\n        \"bar2\",\n    ) {\n    // body\n}\n\nclass Foo6(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(\n        bar1,\n        bar2,\n    ) {\n    // body\n}\n\nclass Foo7(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(\n        bar1,\n        bar2,\n    ),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n\nclass Foo8\n    constructor(\n        val bar1: Bar,\n        val bar2: Bar,\n    ) : FooBar(bar1, bar2),\n        BarFoo1,\n        BarFoo2 {\n        // body\n    }\n
// Assume that max_line_length is not exceeded when written as single line\nclass Foo0()\n\nclass Foo1(a: Any)\n\nclass Foo2(a: Any, b: Any)\n\nclass Foo3(@Foo a: Any, b: Any, c: Any)\n\nclass Foo4(a: Any, b: Any, c: Any) : FooBar(a, c)\n\nclass Foo5 : FooBar(\n    \"bar1\",\n    \"bar2\",\n) {\n    // body\n}\n\nclass Foo6(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(\n    bar1,\n    bar2,\n) {\n    // body\n}\n\nclass Foo7(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(\n    bar1,\n    bar2,\n),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n\nclass Foo8\nconstructor(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(bar1, bar2),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Foo0\n\n// Entire class signature does not fit on single line\nclass Foo1(\n    aVeryLonggggggggggggggggggggggg: Any\n)\n\n// Entire class signature does fit on single line\nclass Foo2(a: Any)\n\n// Entire class signature does not fit on single line\nclass Foo3(\n    aVeryLonggggggggggggggg: Any,\n    b: Any\n)\n\n// Entire class signature does fit on single line\nclass Foo4(a: Any, b: Any)\n\n// Entire class signature does fit on single line\nclass Foo5(@Foo a: Any, b: Any, c: Any)\n\n// Entire class signature does fit on single line\nclass Foo6(a: Any, b: Any, c: Any) :\n    FooBar(a, c)\n\n// Entire class signature (without constructor invocation) does fit on single line\nclass Foo7 :\n    FooBar(\n        \"bar1\",\n        \"bar2\"\n    ) {\n    // body\n}\n\n// Entire class signature (without constructor invocation) does fit on single line\nclass Foo8(val bar1: Bar, val bar2: Bar) :\n    FooBar(\n        bar1,\n        bar2\n    ) {\n    // body\n}\n\n// Entire class signature (without constructor invocation) does not fit on single line\nclass Foo9(\n    val aVeryLonggggggggggggggg: Bar,\n    val bar2: Bar\n) : FooBar(\n    bar1,\n    bar2\n) {\n    // body\n}\n\nclass Foo10(val bar1: Bar, val bar2: Bar) :\n    FooBar(\n        bar1,\n        bar2\n    ),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n\nclass Foo11\nconstructor(\n    val bar1: Bar,\n    val bar2: Bar\n) : FooBar(bar1, bar2),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Foo0()\n\nclass Foo6(a: Any, b: Any, c: Any) : FooBar(a, c)\n\n// Entire class signature (without constructor invocation) does fit on single line\nclass Foo7 : FooBar(\n    \"bar1\",\n    \"bar2\",\n) {\n    // body\n}\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_thanForce wrapping of the parameters of the class signature in case it contains at least the specified number of parameters, even in case the entire class signature would fit on a single line. Use value unset to disable this setting. 1 unset unset max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:class-signature

Warn

For code styles android_studio and intellij_idea this rule rewrites multiline class signature to a single line class signature in case the entire class signature fits on a single line by default. In case you want to leave it to the discretion of the developer to decider whether a single or a multiline class signature is used, please suppress or disable this rule.

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:class-signature\")\n
    Enable rule via .editorconfig
    ktlint_standard_class-signature = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_class-signature = disabled\n
"},{"location":"rules/standard/#enum-entry","title":"Enum entry","text":"

Enum entry names should be uppercase underscore-separated or upper camel-case separated.

Ktlint Disallowed
enum class Bar {\n    FOO,\n    Foo,\n    FOO_BAR,\n    FooBar,\n}\n
enum class Bar {\n    foo,\n    bAr,\n    Foo_Bar,\n}\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_enum_entry_name_casingChoose any of upper_cases (an enum entry may only contain uppercases, and underscores, and digits, and dicritics on letters and strokes), camel_cases (an enum entry may only contain CamelCase values, including digits, and dicritics on letters and strokes), or upper_or_camel_case (allows mixing of uppercase and CamelCase entries as per Kotlin Coding Conventions). upper_or_camel_cases upper_or_camel_cases upper_or_camel_cases

Rule id: standard:enum-entry-name-case

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:enum-entry-name-case\")\n
    Enable rule via .editorconfig
    ktlint_standard_enum-entry-name-case = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_enum-entry-name-case = disabled\n
"},{"location":"rules/standard/#file-name","title":"File name","text":"

A file containing only one visible (e.g. non-private) class, and visible declarations related to that class only, should be named according to that element. The same applies if the file does not contain a visible class but exactly one type alias or one object declaration. Otherwise, the PascalCase notation should be used.

Rule id: standard:filename

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:filename\")\n
    Enable rule via .editorconfig
    ktlint_standard_filename = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_filename = disabled\n
"},{"location":"rules/standard/#final-newline","title":"Final newline","text":"

Ensures consistent usage of a newline at the end of each file.

Configuration setting ktlint_official intellij_idea android_studio insert_final_newline true true true

Rule id: standard:final-newline

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:final-newline\")\n
    Enable rule via .editorconfig
    ktlint_standard_final-newline = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_final-newline = disabled\n
"},{"location":"rules/standard/#function-expression-body","title":"Function expression body","text":"

Rewrites a function body only containing a return or throw expression to an expression body.

Note

If the function body contains a comment, it is not rewritten to an expression body.

Ktlint Disallowed
fun foo1() = \"foo\"\n\nfun foo2(): String = \"foo\"\n\nfun foo3(): Unit = throw IllegalArgumentException(\"some message\")\n\nfun foo4(): Foo = throw IllegalArgumentException(\"some message\")\n\nfun foo5() {\n    return \"foo\" // some comment\n}\n\nfun foo6(): String {\n    /* some comment */\n    return \"foo\"\n}\n\nfun foo7() {\n    throw IllegalArgumentException(\"some message\")\n    /* some comment */\n}\n\nfun foo8(): Foo {\n    throw IllegalArgumentException(\"some message\")\n    // some comment\n}\n
fun foo1() {\n    return \"foo\"\n}\n\nfun foo2(): String {\n    return \"foo\"\n}\n\nfun foo3() {\n    throw IllegalArgumentException(\"some message\")\n}\n\nfun foo4(): Foo {\n    throw IllegalArgumentException(\"some message\")\n}\n

Rule id: standard:function-expression-body

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-expression-body\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-expression-body = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-expression-body = disabled\n
"},{"location":"rules/standard/#function-literal","title":"Function literal","text":"

Enforces the parameters of a function literal and the arrow to be written on the same line as the opening brace if the maximum line length is not exceeded. In case the parameters are wrapped to multiple lines then this is respected.

If the function literal contains multiple parameters and at least one parameter other than the first parameter starts on a new line than all parameters and the arrow are wrapped to separate lines.

Ktlint (ktlint_official) Ktlint (non ktlint_official) Disallowed
val foobar1 = { foo + bar }\nval foobar2 =\n    {\n        foo + bar\n    }\nval foobar3 =\n    { foo: Foo ->\n        foo.repeat(2)\n    }\nval foobar4 =\n    { foo: Foo, bar: Bar ->\n        foo + bar\n    }\nval foobar5 = { foo: Foo, bar: Bar -> foo + bar }\nval foobar6 =\n    {\n        foo: Foo,\n        bar: Bar,\n        ->\n        foo + bar\n    }\n\n// Assume that the last allowed character is\n// at the X character on the right           X\nval foobar7 =\n    barrrrrrrrrrrrrr { \n        fooooooooooooooo: Foo\n        ->\n        foo.repeat(2)\n    }\n
val foobar6 =\n    {\n            foo: Foo,\n            bar: Bar,\n        ->\n        foo + bar\n    }\n\n// Assume that the last allowed character is\n// at the X character on the right           X\nval foobar7 =\n    barrrrrrrrrrrrrr { \n            fooooooooooooooo: Foo\n        ->\n        foo.repeat(2)\n    }\n
val foobar3 =\n    {\n        foo: Foo ->\n        foo.repeat(2)\n    }\nval foobar6 =\n    { foo: Foo,\n      bar: Bar ->\n        foo + bar\n    }\n// Assume that the last allowed character is\n// at the X character on the right           X\nval foobar7 =\n    barrrrrrrrrrrrrr { fooooooooooooooo: Foo ->\n        foo.repeat(2)\n    }\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:function-literal

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-literal\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-literal = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-literal = disabled\n
"},{"location":"rules/standard/#function-signature","title":"Function signature","text":"

Rewrites the function signature to a single line when possible (e.g. when not exceeding the max_line_length property) or a multiline signature otherwise.

Note

Wrapping of parameters is also influenced by the parameter-list-wrapping rule.

Ktlint Disallowed
// Assume that the last allowed character is\n// at the X character on the right           X\nfun foooooooo(\n    a: Any,\n    b: Any,\n    c: Any,\n): String {\n    // body\n}\n\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun bar(a: Any, b: Any, c: Any): String {\n    // body\n}\n\n// When wrapping of body is set to 'default'.\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun f(a: Any, b: Any): String = \"some-result\"\n    .uppercase()\n\n// When wrapping of body is set to 'multiline'\n// or 'always'.\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun f(a: Any, b: Any): String =\n    \"some-result\"\n        .uppercase()\n
// Assume that the last allowed character is\n// at the X character on the right           X\nfun foooooooo(a: Any, b: Any, c: Any): String {\n    // body\n}\n\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun bar(\n    a: Any,\n    b: Any,\n    c: Any\n): String {\n    // body\n}\n\n// When wrapping of body is set to 'default'.\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun f(a: Any, b: Any): String =\n    \"some-result\"\n        .uppercase()\n\n// When wrapping of body is set to 'multiline'\n// or 'always'.\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun f(a: Any, b: Any): String = \"some-result\"\n    .uppercase()\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_function_signature_body_expression_wrappingDetermines how to wrap the body of function in case it is an expression. Use default to wrap the body expression only when the first line of the expression does not fit on the same line as the function signature. Use multiline to force wrapping of body expressions that consists of multiple lines. Use always to force wrapping of body expression always. multiline default default ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_thanForces a multiline function signature in case the function contains the specified minimum number of parameters even in case the function signature would fit on a single line. Use value unset (default) to disable this setting. 2 unset unset default multiline always

When ktlint_function_signature_body_expression_wrapping is set to default, the first line of a body expression is appended to the function signature as long as the max line length is not exceeded.

ktlint_function_signature_body_expression_wrapping=default
// Given that the function signature has to be written as a single line\n// function signature and that the function has a multiline body expression\nfun someFunction(a: Any, b: Any): String = \"some-result\"\n    .uppercase()\n\n// Given that the function signature has to be written as a multiline\n// function signature and that the function has a multiline body expression\nfun someFunction(\n    a: Any,\n    b: Any\n): String = \"some-result\"\n    .uppercase()\n

When ktlint_function_signature_body_expression_wrapping is set to multiline, the body expression starts on a separate line in case it is a multiline expression. A single line body expression is wrapped only when it does not fit on the same line as the function signature.

ktlint_function_signature_body_expression_wrapping=multiline
// Given that the function signature has to be written as a single line\n// function signature and that the function has a single line body expression\n// that fits on the same line as the function signature.\nfun someFunction(a: Any, b: Any): String = \"some-result\".uppercase()\n\n// Given that the function signature has to be written as a multiline\n// function signature and that the function has a single line body expression\n// that fits on the same line as the function signature.\nfun someFunction(\n    a: Any,\n    b: Any\n): String = \"some-result\".uppercase()\n\n// Given that the function signature has to be written as a single line\n// function signature and that the function has a multiline body expression\nfun someFunction(a: Any, b: Any): String =\n    \"some-result\"\n         .uppercase()\n\n// Given that the function signature has to be written as a multiline\n// function signature and that the function has a multiline body expression\nfun someFunction(\n    a: Any,\n    b: Any\n): String =\n    \"some-result\"\n       .uppercase()\n

When ktlint_function_signature_body_expression_wrapping is set to always the body expression is always wrapped to a separate line.

ktlint_function_signature_body_expression_wrapping=always
// Given that the function signature has to be written as a single line\n// function signature and that the function has a single line body expression\nfun someFunction(a: Any, b: Any): String =\n    \"some-result\".uppercase()\n\n// Given that the function signature has to be written as a multiline\n// function signature and that the function has a multiline body expression\nfun functionWithAVeryLongName(\n    a: Any,\n    b: Any\n): String =\n    \"some-result\"\n        .uppercase()\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:function-signature

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-signature\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-signature = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-signature = disabled\n
"},{"location":"rules/standard/#function-type-modifier-spacing","title":"Function type modifier spacing","text":"

Enforce a single whitespace between the modifier list and the function type.

Ktlint Disallowed
val foo: suspend () -> Unit = {}\n\nsuspend fun bar(baz: suspend () -> Unit) = baz()\n
val foo: suspend() -> Unit = {}\n\nsuspend fun bar(baz: suspend   () -> Unit) = baz()\n

Rule id: standard:function-type-modifier-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-type-modifier-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-type-modifier-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-type-modifier-spacing = disabled\n
"},{"location":"rules/standard/#if-else-bracing","title":"If else bracing","text":"

If at least one branch of an if-else statement or an if-else-if statement is wrapped between curly braces then all branches should be wrapped between braces.

Ktlint Disallowed
fun foo(value: Int) {\n    if (value > 0) {\n        doSomething()\n    } else if (value < 0) {\n        doSomethingElse()\n    } else {\n        doSomethingElse2()\n    }\n}\n
fun foo(value: Int) {\n    if (value > 0)\n        doSomething()\n    else if (value < 0) {\n        doSomethingElse()\n    } else\n        doSomethingElse2()\n}\n

Rule id: standard:if-else-bracing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:if-else-bracing\")\n
    Enable rule via .editorconfig
    ktlint_standard_if-else-bracing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_if-else-bracing = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#import-ordering","title":"Import ordering","text":"

Ensures that imports are ordered consistently (see Import Layouts for configuration).

Ktlint Disallowed
import com.bar.Bar\nimport com.foo.Foo\nimport org.foo.bar.FooBar\nimport java.util.concurrent.ConcurrentHashMap\n
import com.bar.Bar\nimport java.util.concurrent.ConcurrentHashMap\nimport org.foo.bar.FooBar\nimport com.foo.Foo\n

Rule id: standard:import-ordering

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:import-ordering\")\n
    Enable rule via .editorconfig
    ktlint_standard_import-ordering = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_import-ordering = disabled\n
"},{"location":"rules/standard/#indentation","title":"Indentation","text":"

Indentation formatting - respects .editorconfig indent_size with no continuation indent (see EditorConfig section for more).

Ktlint Disallowed
fun main() {\n    foobar(\n        a,\n        b,\n        c,\n    )\n}\n
fun main() {\n    foobar(\n          a,\n          b,\n          c,\n          )\n}\n

Note

This rule handles indentation for many different language constructs which can not be summarized with a few examples. See the unit tests for more details.

Configuration setting ktlint_official intellij_idea android_studio indent_sizeThe size of an indentation level when indent_style is set to space. Use value unset to ignore indentation. 4 4 4 indent_styleStyle of indentation. Set this value to space or tab. space space space ij_kotlin_indent_before_arrow_on_new_lineIndent the arrow in a when-entry if the arrow starts on a new line. Set this value to true or false. Starting from IDEA version 2024.2 or above this value needs to be set to true to maintain compatibility with IDEA formatting. false false false

Rule id: standard:indent

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:indent\")\n
    Enable rule via .editorconfig
    ktlint_standard_indent = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_indent = disabled\n
"},{"location":"rules/standard/#naming","title":"Naming","text":""},{"location":"rules/standard/#backing-property-naming","title":"Backing property naming","text":"

Allows property names to start with _ in case the property is a backing property. ktlint_official and android_studio code styles require the correlated property/function to be defined as public.

Ktlint Disallowed
class Bar {\n    // Backing property\n    private val _elementList = mutableListOf<Element>()\n    val elementList: List<Element>\n        get() = _elementList\n}\n
class Bar {\n    // Incomplete backing property as public property 'elementList1' is missing\n    private val _elementList1 = mutableListOf<Element>()\n\n    // Invalid backing property as '_elementList2' is not a private property\n    val _elementList2 = mutableListOf<Element>()\n    val elementList2: List<Element>\n        get() = _elementList2\n}\n

Rule id: standard:backing-property-naming

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:backing-property-naming\")\n
    Enable rule via .editorconfig
    ktlint_standard_backing-property-naming = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_backing-property-naming = disabled\n
"},{"location":"rules/standard/#class-naming","title":"Class naming","text":"

Enforce naming of class and objects.

Ktlint Ktlint JUnit Test Disallowed
class Foo\n\nclass Foo1\n\nclass `class` // Any keyword is allowed when wrapped between backticks\n
@Nested\ninner class `Some descriptive class name` {\n    @Test\n    fun `Some descriptive test name`() {\n        // do something\n    }\n}\n
class foo\nclass Foo_Bar\nclass `Some class in the production code`\n

Note

Functions in files which import a class from package org.junit.jupiter.api are considered to be test functions and are allowed to have a name specified between backticks and do not need to adhere to the normal naming convention. Although, the Kotlin coding conventions does not allow this explicitly for class identifiers, ktlint does allow it.

This rule can also be suppressed with the IntelliJ IDEA inspection suppression ClassName.

Rule id: standard:class-naming

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:class-naming\")\n
    Enable rule via .editorconfig
    ktlint_standard_class-naming = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_class-naming = disabled\n
"},{"location":"rules/standard/#function-naming","title":"Function naming","text":"

Enforce naming of function.

Ktlint Ktlint Test Disallowed
fun foo() {}\n\nfun fooBar() {}\n\nfun `fun`() {} // Any keyword is allowed when wrapped between backticks\n
@Test\nfun `Some name`() {}\n\n@Test\nfun do_something() {}\n
fun Foo() {}\nfun Foo_Bar() {}\nfun `Some name`() {}\nfun do_something() {}\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_function_naming_ignore_when_annotated_withIgnore functions that are annotated with values in this setting. This value is a comma separated list of names without the '@' prefix. unset unset unset

Note

When using Compose, you might want to configure the function-naming rule with .editorconfig property ktlint_function_naming_ignore_when_annotated_with=Composable. Furthermore, you can use a dedicated ktlint ruleset like Compose Rules for checking naming conventions for Composable functions.

Note

Functions in files which import a class from package io.kotest, junit.framework, kotlin.test, org.junit, or org.testng are considered to be test functions. Functions in such classes are allowed to have underscores in the name. Also, function names enclosed between backticks do not need to adhere to the normal naming convention.

This rule can also be suppressed with the IntelliJ IDEA inspection suppression FunctionName.

Rule id: standard:function-naming

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-naming\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-naming = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-naming = disabled\n
"},{"location":"rules/standard/#package-name","title":"Package name","text":"

Validates that the package name matches the regular expression [a-z][a-zA-Z\\d]*(\\.[a-z][a-zA-Z\\d]*)*.

Ktlint Disallowed
package foo\npackage foo.bar\n
package Foo\npackage foo.Foo\npackage `foo bar`\npackage foo.`foo bar`\n

Rule id: standard:package-name

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:package-name\")\n
    Enable rule via .editorconfig
    ktlint_standard_package-name = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_package-name = disabled\n
"},{"location":"rules/standard/#property-naming","title":"Property naming","text":"

Enforce naming of property.

Note

This rule can not reliably detect all situations in which incorrect property naming is used. So it only detects in which it is certain that naming is incorrect.

Ktlint Disallowed
val foo1 = Foo() // In case developers want to tell that Foo is mutable\nval FOO1 = Foo() // In case developers want to tell that Foo is deeply immutable\n\nconst val FOO_BAR = \"FOO-BAR\" // By definition deeply immutable\n\nvar foo2: Foo = Foo() // By definition not immutable\n\nclass Bar {\n    val foo1 = \"foo1\" // Class properties always start with lowercase, const is not allowed\n\n    const val FOO_BAR = \"FOO-BAR\" // By definition deeply immutable\n\n    var foo2: Foo = Foo() // By definition not immutable\n\n    // Backing property\n    private val _elementList = mutableListOf<Element>()\n    val elementList: List<Element>\n        get() = _elementList\n\n    companion object {\n        val foo1 = Foo() // In case developer want to communicate that Foo is mutable\n        val FOO1 = Foo() // In case developer want to communicate that Foo is deeply immutable\n    }\n}\n\nvar `package` = \"foo\" // Any keyword is allowed when wrapped between backticks\n
const val fooBar = \"FOO-BAR\" // By definition deeply immutable\n\nvar FOO2: Foo = Foo() // By definition not immutable\n\nclass Bar {\n    val FOO_BAR = \"FOO-BAR\" // Class properties always start with lowercase, const is not allowed\n\n    // Incomplete backing property as public property 'elementList1' is missing\n    private val _elementList1 = mutableListOf<Element>()\n\n    // Invalid backing property as '_elementList2' is not a private property\n    val _elementList2 = mutableListOf<Element>()\n    val elementList2: List<Element>\n        get() = _elementList2\n}\n

This rule is suppressed whenever the IntelliJ IDEA inspection suppression PropertyName, ConstPropertyName, ObjectPropertyName or PrivatePropertyName is used.

Rule id: standard:property-naming

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:property-naming\")\n
    Enable rule via .editorconfig
    ktlint_standard_property-naming = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_property-naming = disabled\n
"},{"location":"rules/standard/#no-blank-lines-in-list","title":"No blank lines in list","text":"

Disallow blank lines to be used in lists before the first element, between elements, and after the last element.

Super type

Ktlint Disallowed
class FooBar :\n    Foo,\n    Bar {\n    // body\n}\n
class FooBar :\n\n    Foo,\n\n    Bar\n\n{\n    // body\n}\n

Type argument list

Ktlint Disallowed
val foobar: FooBar<\n    Foo,\n    Bar,\n    > = FooBar(Foo(), Bar())\n
val foobar: FooBar<\n\n    Foo,\n\n    Bar,\n\n    > = FooBar(Foo(), Bar())\n

Type constraint list

Ktlint Disallowed
class BiAdapter<C : RecyclerView.ViewHolder, V1 : C, V2 : C, out A1, out A2>(\n    val adapter1: A1,\n    val adapter2: A2,\n) : RecyclerView.Adapter<C>()\n    where A1 : RecyclerView.Adapter<V1>, A1 : ComposableAdapter.ViewTypeProvider,\n          A2 : RecyclerView.Adapter<V2>, A2 : ComposableAdapter.ViewTypeProvider {\n    // body\n}\n
class BiAdapter<C : RecyclerView.ViewHolder, V1 : C, V2 : C, out A1, out A2>(\n    val adapter1: A1,\n    val adapter2: A2\n) : RecyclerView.Adapter<C>()\n    where\n          A1 : RecyclerView.Adapter<V1>, A1 : ComposableAdapter.ViewTypeProvider,\n\n          A2 : RecyclerView.Adapter<V2>, A2 : ComposableAdapter.ViewTypeProvider\n{\n    // body\n}\n

Type parameter list

Ktlint Disallowed
fun <\n    Foo,\n    Bar,\n    > foobar()\n
fun <\n\n    Foo,\n\n    Bar,\n\n    > foobar()\n

Value argument list

Ktlint Disallowed
val foobar =\n    foobar(\n        \"foo\",\n        \"bar\",\n    )\n
val foobar = \n    foobar(\n\n      \"foo\",\n\n      \"bar\",\n\n  )\n

Value parameter list

Ktlint Disallowed
fun foobar(\n    foo: String,\n    bar: String,\n)\n
fun foobar(\n\n    foo: String,\n\n    bar: String,\n\n)\n

Rule id: standard:no-blank-line-in-list

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-blank-line-in-list\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-blank-line-in-list = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-blank-line-in-list = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#no-consecutive-comments","title":"No consecutive comments","text":"

Consecutive comments are disallowed in following cases: - Any mix of a consecutive kdoc, a block comment or an EOL comment unless separated by a blank line in between - Consecutive KDocs (even when separated by a blank line) - Consecutive block comments (even when separated by a blank line)

Consecutive EOL comments are always allowed as they are often used instead of a block comment.

Ktlint Disallowed
// An EOL comment\n// may be followed by another EOL comment\nval foo = \"foo\"\n\n// Different comment types (including KDoc) may be consecutive ..\n\n/*\n * ... but do need to be separated by a blank line ...\n */\n\n/**\n  * ... but a KDoc can not be followed by an EOL or a block comment or another KDoc\n  */\nfun bar() = \"bar\"\n
/*\n * Block comments can not be consecutive ...\n */\n/*\n * ... even not when separated by a new line.\n */\nval bar = \"bar\" \n\n/**\n  * A KDoc can not be followed by a block comment or an EOL comment or another KDOC\n  */\n\n// ... even not when separated by a new line.\n

Rule id: standard:no-consecutive-comments

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-consecutive-comments\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-consecutive-comments = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-consecutive-comments = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#no-empty-file","title":"No empty file","text":"

A kotlin (script) file should not be empty. It needs to contain at least one declaration. Files only contain a package and/or import statements are as of that disallowed.

Rule id: standard:no-empty-file

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-empty-file\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-empty-file = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-empty-file = disabled\n
"},{"location":"rules/standard/#no-empty-first-line-at-start-in-class-body","title":"No empty first line at start in class body","text":"

Detect blank lines at start of a class body.

Ktlint Disallowed
class Foo {\n    val foo = \"foo\"\n}\n
class Foo {\n\n    val foo = \"foo\"\n}\n

Rule id: standard:no-empty-first-line-in-class-body

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-empty-first-line-in-class-body\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-empty-first-line-in-class-body = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-empty-first-line-in-class-body = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#no-single-line-block-comment","title":"No single line block comment","text":"

A single line block comment should be replaced with an EOL comment when possible.

Ktlint Disallowed
/*\n * Some comment\n */\nval foo = \"foo\" // Some comment\nval foo = { /* no-op */ }\n
/* Some comment */\nval foo = \"foo\" /* Some comment */\n

Rule id: standard:no-single-line-block-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-single-line-block-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-single-line-block-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-single-line-block-comment = disabled\n
"},{"location":"rules/standard/#ktlint-suppression-rule","title":"Ktlint-suppression rule","text":"

The ktlint-disable and ktlint-enable directives are no longer supported as of ktlint version 0.50.0. This rule migrates the directives to Suppress or SuppressWarnings annotations.

Identifiers in the @Suppress and @SuppressWarnings annotations to suppress ktlint rules are checked for validity and autocorrected when possible.

Ktlint Disallowed
@file:Suppress(\"ktlint:standard:no-wildcard-imports\")\n\nclass FooBar {\n    @Suppress(\"ktlint:standard:max-line-length\")\n    val foo = \"some longggggggggggggggggggg text\"\n\n    fun bar() =\n        @Suppress(\"ktlint:standard:no-multi-spaces\")\n        listOf(\n            \"1   One\", \n            \"10  Ten\", \n            \"100 Hundred\", \n        )\n}\n
/* ktlint-disable standard:no-wildcard-imports */\n\nclass FooBar {\n    val foo = \"some longggggggggggggggggggg text\" // ktlint-disable standard:max-line-length\n\n    fun bar() =\n        listOf(\n            /* ktlint-disable standard:no-multi-spaces */\n            \"1   One\", \n            \"10  Ten\", \n            \"100 Hundred\", \n            /* ktlint-enable standard:no-multi-spaces */\n        )\n}\n

Rule id: standard:ktlint-suppression

Note

This rule cannot be suppressed via @Suppress or be disabled in the .editorconfig.

"},{"location":"rules/standard/#max-line-length","title":"Max line length","text":"

Ensures that lines do not exceed the maximum length of a line as specified in .editorconfig property max_line_length.

This rule does not apply in a number of situations. The .editorconfig property ktlint_ignore_back_ticked_identifier can be set to ignore identifiers which are enclosed in backticks, which for example is very useful when you want to allow longer names for unit tests.

Ktlint Disallowed
// Assume that the last allowed character is\n// at the X character on the right           X\n// Lines below are accepted although the max\n// line length is exceeded.\npackage com.toooooooooooooooooooooooooooo.long\nimport com.tooooooooooooooooooooooooooooo.long\n\nval foo1 =\n    \"\"\"\n    fooooooooooooooooooooooooooooooooooooooooo\n    \"\"\"\n\nval foo2 =\n    \"fooooooooooooooooooooooooooooooooooooooo\"\n\n@Test\nfun `Test description which is toooooooooooo long`() {\n}\n
// Assume that the last allowed character is\n// at the X character on the right           X\nval fooooooooooooooo = \"fooooooooooooooooooooo\"\nval foo = \"foo\" + \"ooooooooooooooooooooooooooo\"\nval foooooooooooooo = \"foooooooooooooooooooo\" // some comment\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_ignore_back_ticked_identifierDefines whether the backticked identifier (``) should be ignored. false false false max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:max-line-length

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:max-line-length\")\n
    Enable rule via .editorconfig
    ktlint_standard_max-line-length = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_max-line-length = disabled\n
"},{"location":"rules/standard/#modifier-order","title":"Modifier order","text":"

Consistent order of modifiers

Ktlint Disallowed
abstract class A {\n    protected open val v = \"\"\n\n    internal open suspend fun f(v: Any): Any = \"\"\n\n    protected lateinit var lv: String\n}\n
abstract class A {\n    open protected val v = \"\"\n\n    open suspend internal fun f(v: Any): Any = \"\"\n\n    lateinit protected var lv: String\n}\n

Rule id: standard:modifier-order

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:modifier-order\")\n
    Enable rule via .editorconfig
    ktlint_standard_modifier-order = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_modifier-order = disabled\n
"},{"location":"rules/standard/#multiline-if-else","title":"Multiline if-else","text":"

Braces required for multiline if/else statements.

Ktlint Disallowed
val foo =\n    if (true) {\n        return 0\n    } else {\n        return 1\n    }\n
val foo =\n    if (true)\n        return 0\n    else\n        return 1\n

Rule id: standard:multiline-if-else

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:multiline-if-else\")\n
    Enable rule via .editorconfig
    ktlint_standard_multiline-if-else = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_multiline-if-else = disabled\n
"},{"location":"rules/standard/#multiline-loop","title":"Multiline loop","text":"

Braces required for multiline for, while, and do statements.

Ktlint Disallowed
for (i in 1..10) {\n    println(i)\n}\n
for (i in 1..10)\n    println(i)\n

Rule id: standard:multiline-loop

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:multiline-loop\")\n
    Enable rule via .editorconfig
    ktlint_standard_multiline-loop = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_multiline-loop = disabled\n
"},{"location":"rules/standard/#no-blank-lines-before","title":"No blank lines before }","text":"

No blank lines before }.

Ktlint Disallowed
fun main() {\n    fun a() {\n    }\n\n    fun b()\n}\n
fun main() {\n    fun a() {\n\n    }\n    fun b()\n\n}\n

Rule id: standard:no-blank-line-before-rbrace

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-blank-line-before-rbrace\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-blank-line-before-rbrace = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-blank-line-before-rbrace = disabled\n
"},{"location":"rules/standard/#no-blank-lines-in-chained-method-calls","title":"No blank lines in chained method calls","text":"Ktlint Disallowed
fun foo(inputText: String) {\n    inputText\n        .lowercase(Locale.getDefault())\n}\n
fun foo(inputText: String) {\n    inputText\n\n        .lowercase(Locale.getDefault())\n}\n

Rule id: standard:no-blank-lines-in-chained-method-calls

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-blank-lines-in-chained-method-calls\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-blank-lines-in-chained-method-calls = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-blank-lines-in-chained-method-calls = disabled\n
"},{"location":"rules/standard/#no-consecutive-blank-lines","title":"No consecutive blank lines","text":"Ktlint Disallowed
package com.test\n\nimport com.test.util\n\nval a = \"a\"\n\nfun b() {\n}\n\nfun c()\n
package com.test\n\n\nimport com.test.util\n\n\nval a = \"a\"\n\n\nfun b() {\n}\n\n\nfun c()\n

Rule id: standard:no-consecutive-blank-lines

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-consecutive-blank-lines\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-consecutive-blank-lines = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-consecutive-blank-lines = disabled\n
"},{"location":"rules/standard/#no-empty-class-bodies","title":"No empty ({}) class bodies","text":"Ktlint Disallowed
class C\n\ndata class DC(val v: Any)\n\ninterface I\n\nobject O\n
class C {}\n\ndata class DC(val v: Any) { }\n\ninterface I {\n}\n\nobject O{}\n

Rule id: standard:no-empty-class-body

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-empty-class-body\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-empty-class-body = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-empty-class-body = disabled\n
"},{"location":"rules/standard/#no-leading-empty-lines-in-method-blocks","title":"No leading empty lines in method blocks","text":"Ktlint Disallowed
fun bar() {\n   val a = 2\n}\n
fun bar() {\n\n   val a = 2\n}\n

Rule id: standard:no-empty-first-line-in-method-block

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-empty-first-line-in-method-block\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-empty-first-line-in-method-block = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-empty-first-line-in-method-block = disabled\n
"},{"location":"rules/standard/#no-line-break-after-else","title":"No line break after else","text":"

Disallows line breaks after the else keyword if that could lead to confusion, for example:

Ktlint Disallowed
fun funA() {\n    if (conditionA()) {\n        doSomething()\n    } else if (conditionB()) {\n        doAnotherThing()\n    }\n}\n
fun funA() {\n    if (conditionA()) {\n        doSomething()\n    } else\n    if (conditionB()) {\n        doAnotherThing()\n    }\n}\n

Rule id: standard:no-line-break-after-else

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-line-break-after-else\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-line-break-after-else = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-line-break-after-else = disabled\n
"},{"location":"rules/standard/#no-line-break-before-assignment","title":"No line break before assignment","text":"

When a line is broken at an assignment (=) operator the break comes after the symbol.

Ktlint Disallowed
val valA =\n    \"\"\n
val valA\n    = \"\"\n

Rule id: standard:no-line-break-before-assignment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-line-break-before-assignment\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-line-break-before-assignment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-line-break-before-assignment = disabled\n
"},{"location":"rules/standard/#no-multi-spaces","title":"No multi spaces","text":"

Except in indentation and in KDoc's it is not allowed to have multiple consecutive spaces.

Ktlint Disallowed
fun main() {\n    x(1, 3)\n}\n
fun  main()  {\n    x(1,  3)\n}\n

Rule id: standard:no-multi-spaces

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-multi-spaces\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-multi-spaces = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-multi-spaces = disabled\n
"},{"location":"rules/standard/#no-semicolons","title":"No semicolons","text":"

Avoid using unnecessary semicolons.

Ktlint Disallowed
fun foo() {\n    bar()\n\n    bar()\n}\n
fun foo() {\n    ;\n    bar()\n    ;\n\n    bar()\n\n    ;\n}\n

Rule id: standard:no-semi

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-semi\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-semi = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-semi = disabled\n
"},{"location":"rules/standard/#no-trailing-whitespaces","title":"No trailing whitespaces","text":"

Rule id: standard:no-trailing-spaces

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-trailing-spaces\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-trailing-spaces = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-trailing-spaces = disabled\n
"},{"location":"rules/standard/#no-unit-as-return-type","title":"No Unit as return type","text":"

The Unit type is not allowed as return-type of a function.

Ktlint Disallowed
fun fn() {}\n
fun fn(): Unit {}\n

Rule id: standard:no-unit-return

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-unit-return\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-unit-return = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-unit-return = disabled\n
"},{"location":"rules/standard/#no-unused-imports","title":"No unused imports","text":"

Warning

This rule is not able to detect all unused imports as mentioned in this issue comment.

Rule id: standard:no-unused-imports

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-unused-imports\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-unused-imports = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-unused-imports = disabled\n
"},{"location":"rules/standard/#no-wildcard-imports","title":"No wildcard imports","text":"

No wildcard imports except whitelisted imports.

Ktlint Disallowed
import foobar.Bar\nimport foobar.Foo\n
import foobar.*\n
Configuration setting ktlint_official intellij_idea android_studio ij_kotlin_packages_to_use_import_on_demandDefines allowed wildcard imports as a comma separated list. - java.util.*,kotlinx.android.synthetic.** java.util.*,kotlinx.android.synthetic.**

Warning

In case property ij_kotlin_packages_to_use_import_on_demand is not explicitly set, Intellij IDEA allows wildcards imports like java.util.* which lead to conflicts with the no-wildcard-imports rule. See Intellij IDEA configuration to prevent such conflicts.

Configuration setting ij_kotlin_packages_to_use_import_on_demand is a comma separated string of import paths. This can be a full path, e.g. \"java.util.List.\", or a wildcard path, e.g. \"kotlin.\". Use \"*\" as wildcard for package and all subpackages.

The layout can be composed by the following symbols:

Examples:

ij_kotlin_imports_layout=* # alphabetical with capital letters before lower case letters (e.g. Z before a), no blank lines\nij_kotlin_imports_layout=*,java.**,javax.**,kotlin.**,^ # default IntelliJ IDEA style, same as alphabetical, but with \"java\", \"javax\", \"kotlin\" and alias imports in the end of the imports list\nij_kotlin_imports_layout=android.**,|,^org.junit.**,kotlin.io.Closeable.*,|,*,^ # custom imports layout\n

Rule id: standard:no-wildcard-imports

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-wildcard-imports\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-wildcard-imports = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-wildcard-imports = disabled\n
"},{"location":"rules/standard/#spacing","title":"Spacing","text":""},{"location":"rules/standard/#angle-bracket-spacing","title":"Angle bracket spacing","text":"

No spaces around angle brackets when used for typing.

Ktlint Disallowed
val a: Map<Int, String> = mapOf()\nval b: Map<Int, String> = mapOf()\nval c: Map<Int, String> = mapOf()\n
val a: Map< Int, String> = mapOf()\nval b: Map<Int, String > = mapOf()\nval c: Map <Int, String> = mapOf()\n

Rule id: standard:spacing-around-angle-brackets

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:spacing-around-angle-brackets\")\n
    Enable rule via .editorconfig
    ktlint_standard_spacing-around-angle-brackets = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_spacing-around-angle-brackets = disabled\n
"},{"location":"rules/standard/#annotation-spacing","title":"Annotation spacing","text":"

Annotations should be separated by a single line break.

Ktlint Disallowed
@JvmField\nfun foo() {}\n\n/**\n * block comment\n */\n@Foo @Bar\nclass FooBar {\n}\n
@JvmField\n\nfun foo() {}\n\n@Foo @Bar\n/**\n * block comment\n */\nclass FooBar {\n}\n

Rule id: standard:annotation-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:annotation-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_annotation-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_annotation-spacing = disabled\n
"},{"location":"rules/standard/#blank-line-between-declarations-with-annotations","title":"Blank line between declarations with annotations","text":"

Declarations with annotations should be separated by a blank line.

Ktlint Disallowed
fun a()\n\n@Bar\nfun b()\n
fun a()\n@Bar\nfun b()\n

Rule id: standard:spacing-between-declarations-with-annotations

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:spacing-between-declarations-with-annotations\")\n
    Enable rule via .editorconfig
    ktlint_standard_spacing-between-declarations-with-annotations = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_spacing-between-declarations-with-annotations = disabled\n
"},{"location":"rules/standard/#blank-line-between-declaration-with-comments","title":"Blank line between declaration with comments","text":"

Declarations with comments should be separated by a blank line.

Ktlint Disallowed
// some comment 1\nbar()\n\n/*\n * some comment 2\n */\nfoo()\n
// some comment 1\nbar()\n/*\n * some comment 2\n */\nfoo()\n

Rule id: standard:spacing-between-declarations-with-comments

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:spacing-between-declarations-with-comments\")\n
    Enable rule via .editorconfig
    ktlint_standard_spacing-between-declarations-with-comments = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_spacing-between-declarations-with-comments = disabled\n
"},{"location":"rules/standard/#colon-spacing","title":"Colon spacing","text":"

Consistent spacing around colon.

Ktlint Disallowed
class A : B\n\nclass A2 : B2\n
class A:B\n\nclass A2  :  B2\n

Rule id: standard:colon-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:colon-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_colon-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_colon-spacing = disabled\n
"},{"location":"rules/standard/#comma-spacing","title":"Comma spacing","text":"

Consistent spacing around comma.

Ktlint Disallowed
val foo1 = Foo(1, 3)\nval foo2 = Foo(1, 3)\n
val foo1 = Foo(1 ,3)\nval foo2 = Foo(1,3)\n

Rule id: standard:comma-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:comma-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_comma-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_comma-spacing = disabled\n
"},{"location":"rules/standard/#comment-spacing","title":"Comment spacing","text":"

The end of line comment sign // should be preceded and followed by exactly a space.

Ktlint Disallowed
// comment\nvar debugging = false // comment\nvar debugging = false // comment\nvar debugging = false // comment\n\nfun main() {\n    System.out.println(\n        // comment\n        \"test\",\n    )\n} // comment\n
//comment\nvar debugging = false// comment\nvar debugging = false //comment\nvar debugging = false//comment\n\nfun main() {\n    System.out.println(\n         //123\n        \"test\"\n    )\n}//comment\n

Rule id: standard:comment-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:comment-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_comment-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_comment-spacing = disabled\n
"},{"location":"rules/standard/#curly-spacing","title":"Curly spacing","text":"

Consistent spacing around curly braces.

Ktlint Disallowed
val foo = bar { foo() }\n
val foo = bar{foo()}\n

Rule id: standard:curly-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:curly-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_curly-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_curly-spacing = disabled\n
"},{"location":"rules/standard/#dot-spacing","title":"Dot spacing","text":"

Consistent spacing around dots.

Ktlint Disallowed
fun String.foo() = \"foo\"\n
fun String . foo() = \"foo\"\n

Rule id: standard:dot-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:dot-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_dot-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_dot-spacing = disabled\n
"},{"location":"rules/standard/#double-colon-spacing","title":"Double colon spacing","text":"

No spaces around ::.

Ktlint Disallowed
val foo = Foo::class\n
val foo1 = Foo ::class\nval foo2 = Foo:: class\nval foo3 = Foo :: class\nval foo4 = Foo::\n    class\n

Rule id: standard:double-colon-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:double-colon-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_double-colon-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_double-colon-spacing = disabled\n
"},{"location":"rules/standard/#function-return-type-spacing","title":"Function return type spacing","text":"

Consistent spacing around the function return type.

Ktlint Disallowed
fun foo(): String = \"some-result\"\n
fun foo1() : String = \"some-result\"\n\nfun foo2():  String = \"some-result\"\n\nfun foo3():String = \"some-result\"\n\nfun foo4():\n    String = \"some-result\"\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:function-return-type-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-return-type-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-return-type-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-return-type-spacing = disabled\n
"},{"location":"rules/standard/#function-start-of-body-spacing","title":"Function start of body spacing","text":"

Consistent spacing before start of function body.

Ktlint Disallowed
// In case `ktlint_function_signature_body_expression_wrapping` is set to `default` or `multiline`\nfun foo1() = \"some-result\"\n\n// In case `ktlint_function_signature_body_expression_wrapping` is set to `always`\nfun foo2() =\n    \"some-result\"\n\nfun foo3() {\n    // do something\n}\n\n// In case `ktlint_function_signature_body_expression_wrapping` is set to `default` or `multiline`\nfun bar1(): String = \"some-result\"\n\n// In case `ktlint_function_signature_body_expression_wrapping` is set to `always`\nfun bar2(): String =\n    \"some-result\"\n\nfun bar3(): String {\n    doSomething()\n    return \"some-result\"\n}\n
fun foo1()= \"some-result\"\n\nfun foo2()\n    = \"some-result\"\n\nfun foo3()\n{\n    // do something\n}\n\nfun bar1(): String= \"some-result\"\n\nfun bar2(): String\n    = \"some-result\"\n\nfun bar3(): String\n{\n    return \"some-result\"\n}\n

Rule id: standard:function-start-of-body-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-start-of-body-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-start-of-body-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-start-of-body-spacing = disabled\n
"},{"location":"rules/standard/#function-type-reference-spacing","title":"Function type reference spacing","text":"

Consistent spacing in the type reference before a function.

Ktlint Disallowed
fun String.foo() = \"some-result\"\n
fun String .foo() = \"some-result\"\nfun String\n    .foo() = \"some-result\"\nfun String? .foo() = \"some-result\"\nfun String?\n    .foo() = \"some-result\"\n

Rule id: standard:function-type-reference-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-type-reference-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-type-reference-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-type-reference-spacing = disabled\n
"},{"location":"rules/standard/#fun-keyword-spacing","title":"Fun keyword spacing","text":"

Consistent spacing after the fun keyword.

Ktlint Disallowed
fun foo() = \"some-result\"\n
fun  foo() = \"some-result\"\nfun\nfoo() = \"some-result\"\n

Rule id: standard:fun-keyword-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:fun-keyword-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_fun-keyword-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_fun-keyword-spacing = disabled\n
"},{"location":"rules/standard/#kdoc-wrapping","title":"Kdoc wrapping","text":"

A KDoc comment should start and end on a line that does not contain any other element.

Ktlint Disallowed
/** Some KDoc comment 1 */\nval foo1 = \"foo1\"\n
/** Some KDoc comment 1 */ val foo1 = \"foo1\"\nval foo2 = \"foo2\" /** Some KDoc comment\n                   * with a newline\n                   */\n

Rule id: standard:kdoc-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:kdoc-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_kdoc-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_kdoc-wrapping = disabled\n
"},{"location":"rules/standard/#keyword-spacing","title":"Keyword spacing","text":"

Consistent spacing around keywords.

Ktlint Disallowed
fun main() {\n    if (true) {\n        doSomething()\n    }\n}\n
fun main() {\n    if(true) {\n        doSomething()\n    }\n}\n

Rule id: standard:keyword-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:keyword-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_keyword-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_keyword-spacing = disabled\n
"},{"location":"rules/standard/#modifier-list-spacing","title":"Modifier list spacing","text":"

Consistent spacing between modifiers in and after the last modifier in a modifier list.

Ktlint Disallowed
abstract class Foo {\n    protected abstract suspend fun execute()\n}\n
abstract  class Foo {\n    protected  abstract  suspend  fun execute()\n}\nabstract\nclass Foo {\n    protected\n    abstract\n    suspend\n    fun execute()\n}\n

Rule id: standard:modifier-list-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:modifier-list-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_modifier-list-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_modifier-list-spacing = disabled\n
"},{"location":"rules/standard/#nullable-type-spacing","title":"Nullable type spacing","text":"

No spaces in a nullable type.

Ktlint Disallowed
val foo: String? = null\nval foo: List<String?> = listOf(null)\n
val foo: String ? = null\nval foo: List<String ?> = listOf(null)\n

Rule id: standard:nullable-type-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:nullable-type-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_nullable-type-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_nullable-type-spacing = disabled\n
"},{"location":"rules/standard/#operator-spacing","title":"Operator spacing","text":"

Consistent spacing around operators.

Ktlint Disallowed
val foo1 = 1 + 2\nval foo2 = 1 - 2\nval foo3 = 1 * 2\nval foo4 = 1 / 2\n
val foo1 = 1+2\nval foo2 = 1- 2\nval foo3 = 1 *2\nval foo4 = 1  /  2\n

Rule id: standard:op-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:op-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_op-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_op-spacing = disabled\n
"},{"location":"rules/standard/#parameter-list-spacing","title":"Parameter list spacing","text":"

Consistent spacing inside the parameter list.

Ktlint Disallowed
fun foo(a: Any) = \"some-result\"\n\nfun foo() = \"some-result\"\n
fun foo( a : Any ) = \"some-result\"\nfun foo(\n) = \"some-result\"\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:parameter-list-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:parameter-list-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_parameter-list-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_parameter-list-spacing = disabled\n
"},{"location":"rules/standard/#parenthesis-spacing","title":"Parenthesis spacing","text":"

Consistent spacing around parenthesis.

Ktlint Disallowed
class Foo : Bar {\n    constructor(string: String) : super()\n}\n\nval foo1 = ((1 + 2) / 3)\n
class Foo : Bar {\n    constructor(string: String) : super ()\n}\n\nval foo1 = ( (1 + 2 ) / 3)\n

Rule id: standard:paren-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:paren-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_paren-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_paren-spacing = disabled\n
"},{"location":"rules/standard/#range-spacing","title":"Range spacing","text":"

Consistent spacing around range operators.

Ktlint Disallowed
val foo1 = (1..12 step 2).last\nval foo2 = (1..12 step 2).last\nval foo3 = (1..12 step 2).last\n
val foo1 = (1.. 12 step 2).last\nval foo2 = (1 .. 12 step 2).last\nval foo3 = (1 ..12 step 2).last\n

Rule id: standard:range-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:range-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_range-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_range-spacing = disabled\n
"},{"location":"rules/standard/#spacing-between-function-name-and-opening-parenthesis","title":"Spacing between function name and opening parenthesis","text":"

Consistent spacing between function name and opening parenthesis.

Ktlint Disallowed
fun foo() = \"foo\"\n
fun foo () = \"foo\"\n

Rule id: standard:spacing-between-function-name-and-opening-parenthesis

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:spacing-between-function-name-and-opening-parenthesis\")\n
    Enable rule via .editorconfig
    ktlint_standard_spacing-between-function-name-and-opening-parenthesis = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_spacing-between-function-name-and-opening-parenthesis = disabled\n
"},{"location":"rules/standard/#try-catch-finally-spacing","title":"Try catch finally spacing","text":"

Enforce consistent spacing in try { .. } catch { .. } finally { .. }.

Ktlint Disallowed
fun foo() =\n    try {\n        // do something\n    } catch (exception: Exception) {\n        // handle exception\n    } finally {\n        // clean up\n    }\n
fun foo1() = try { /* ... */ } catch (exception: Exception) { /* ... */ } finally { /* ... */ }\nfun foo2() = \n    try {\n        // do something\n    }\n    catch (exception: Exception) {\n        // handle exception\n    }\n    finally {\n        // clean up\n    }\n

Rule id: standard:try-catch-finally-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:try-catch-finally-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_try-catch-finally-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_try-catch-finally-spacing = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#type-argument-list-spacing","title":"Type argument list spacing","text":"

Spacing before and after the angle brackets of a type argument list.

Ktlint Disallowed
val res = ArrayList<LintError>()\n\nclass B<T> : A<T>() {\n    override fun x() = super<A>.x()\n}\n
val res = ArrayList < LintError > ()\n\nclass B<T> : A< T >() {\n    override fun x() = super< A >.x()\n}\n

Rule id: standard:type-argument-list-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:type-argument-list-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_type-argument-list-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_type-argument-list-spacing = disabled\n
"},{"location":"rules/standard/#type-parameter-list-spacing","title":"Type parameter list spacing","text":"

Spacing after a type parameter list in function and class declarations.

Ktlint Disallowed
fun <T> foo1(t: T) = \"some-result\"\n\nfun <T> foo2(t: T) = \"some-result\"\n\nfun <T> foo3(t: T) = \"some-result\"\n
fun<T> foo1(t: T) = \"some-result\"\n\nfun <T>foo2(t: T) = \"some-result\"\n\nfun<T>foo3(t: T) = \"some-result\"\n

Rule id: standard:type-parameter-list-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:type-parameter-list-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_type-parameter-list-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_type-parameter-list-spacing = disabled\n
"},{"location":"rules/standard/#unary-operator-spacing","title":"Unary operator spacing","text":"

No spaces around unary operators.

Ktlint Disallowed
fun foo1(i: Int) = i++\n\nfun foo2(i: Int) = ++i\n\nfun foo3(i: Int) = ++i\n
fun foo1(i: Int) = i ++\n\nfun foo2(i: Int) = ++ i\n\nfun foo3(i: Int) = ++\n    i\n

Rule id: standard:unary-op-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:unary-op-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_unary-op-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_unary-op-spacing = disabled\n
"},{"location":"rules/standard/#string-template","title":"String template","text":"

Consistent string templates ($v instead of ${v}, ${p.v} instead of ${p.v.toString()})

Ktlint Disallowed
val foo = \"$foo hello\"\n
val foo = \"${foo} hello\"\n

Rule id: standard:string-template

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:string-template\")\n
    Enable rule via .editorconfig
    ktlint_standard_string-template = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_string-template = disabled\n
"},{"location":"rules/standard/#string-template-indent","title":"String template indent","text":"

Enforce consistent string template indentation for multiline string templates which are post-fixed with .trimIndent(). The opening and closing \"\"\" are placed on separate lines and the indentation of the content of the template is aligned with the \"\"\".

Ktlint Disallowed
val foo =\n    \"\"\"\n    line1\n    line2\n    \"\"\".trimIndent()\n\nfun foo() {\n    // The opening \"\"\" can not be wrapped to next line as that would result in a compilation error\n    return \"\"\"\n        line1\n        line2\n        \"\"\".trimIndent()\n}\n
val foo = \"\"\"\n          line1\n          line2\n          \"\"\".trimIndent()\n\nfun foo() {\n    return \"\"\"\n        line1\n        line2\n    \"\"\".trimIndent()\n}\n

Rule id: standard:string-template-indent

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:string-template-indent\")\n
    Enable rule via .editorconfig
    ktlint_standard_string-template-indent = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_string-template-indent = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#trailing-comma-on-call-site","title":"Trailing comma on call site","text":"

Consistent removal (default) or adding of trailing commas on call site.

Ktlint Disallowed
val foo =\n    FooWrapper(\n        Foo(\n            a = 3,\n            b = 4,\n        ),\n    )\n
val foo =\n    FooWrapper(Foo(\n        a = 3,\n        b = 4,\n    ),) // it's weird to insert \",\" between unwrapped (continued) parenthesis\n
Configuration setting ktlint_official intellij_idea android_studio ij_kotlin_allow_trailing_comma_on_call_siteDefines whether a trailing comma (or no trailing comma) should be enforced on the calling site, e.g. argument-list, when-entries, lambda-arguments, indices, etc. When set, IntelliJ IDEA uses this property to allow usage of a trailing comma by discretion of the developer. KtLint however uses this setting to enforce consistent usage of the trailing comma when set. true true false

Note

Although the Kotlin coding conventions leaves it to the developer's discretion to use trailing commas on the call site, it also states that usage of trailing commas has several benefits:

KtLint values consistent formatting more than a per-situation decision, and therefore uses this setting to enforce/disallow usage of trailing comma's on the calling site.

Rule id: standard:trailing-comma-on-call-site

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:trailing-comma-on-call-site\")\n
    Enable rule via .editorconfig
    ktlint_standard_trailing-comma-on-call-site = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_trailing-comma-on-call-site = disabled\n
"},{"location":"rules/standard/#trailing-comma-on-declaration-site","title":"Trailing comma on declaration site","text":"

Consistent removal (default) or adding of trailing commas on declaration site.

Ktlint Disallowed
class FooWrapper(\n    val foo = Foo(\n        a = 3,\n        b = 4,\n    ),\n)\n
class FooWrapper(val foo = Foo(\n    a = 3,\n    b = 4,\n),) // it's weird to insert \",\" between unwrapped (continued) parenthesis\n
Configuration setting ktlint_official intellij_idea android_studio ij_kotlin_allow_trailing_commaDefines whether a trailing comma (or no trailing comma) should be enforced on the defining site, e.g. parameter-list, type-argument-list, lambda-value-parameters, enum-entries, etc. When set, IntelliJ IDEA uses this property to allow usage of a trailing comma by discretion of the developer. KtLint however uses this setting to enforce consistent usage of the trailing comma when set. true true false

Note

The Kotlin coding conventions encourages the usage of trailing commas on the declaration site, but leaves it to the developer's discretion to use trailing commas on the call site. But next to this, it also states that usage of trailing commas has several benefits:

KtLint values consistent formatting more than a per-situation decision, and therefore uses this setting to enforce/disallow usage of trailing comma's in declarations.

Rule id: standard:trailing-comma-on-declaration-site

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:trailing-comma-on-declaration-site\")\n
    Enable rule via .editorconfig
    ktlint_standard_trailing-comma-on-declaration-site = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_trailing-comma-on-declaration-site = disabled\n
"},{"location":"rules/standard/#type-argument-comment","title":"Type argument comment","text":"

Disallows comments to be placed at certain locations inside a type argument.

Ktlint Disallowed
fun Foo<\n    /* some comment */ \n    out Any\n    >.foo() {}\nfun Foo<\n    // some comment \n    out Any\n    >.foo() {}\n
fun Foo<out /* some comment */ Any>.foo() {}\nfun Foo<\n    out Any, // some comment\n    >.foo() {}\n

Note

In some projects it is an accepted practice to use EOL comments to document the parameter before the comma as is shown below:

fun Foo<\n    out Bar1, // some comment\n    out Bar2, // some other comment\n>.foo() {}\n
Although this code sample might look ok, it is semantically and programmatically unclear to which type some comment refers. From the developer perspective it might be clear that it belongs to type Bar1. From the parsers perspective, it does belong to type Bar2.

Rule id: standard:type-argument-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:type-argument-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_type-argument-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_type-argument-comment = disabled\n
"},{"location":"rules/standard/#type-parameter-comment","title":"Type parameter comment","text":"

Disallows comments to be placed at certain locations inside a type parameter.

Ktlint Disallowed
class Foo1<\n    /* some comment */ \n    out Bar\n    >\nclass Foo2<\n    // some comment \n    out Bar\n    >\n
class Foo1<in /* some comment */ Bar>\nclass Foo2<\n    in Bar, // some comment\n    >\n

Note

In some projects it is an accepted practice to use EOL comments to document the parameter before the comma as is shown below:

class Foo<\n    out Bar1, // some comment\n    out Bar2, // some other comment\n>\n

Although this code sample might look ok, it is semantically and programmatically unclear on which parameter some comment refers. From the developer perspective it might be clear that it belongs to type Bar1. From the parsers perspective, it does belong to type Bar2.

Rule id: standard:type-parameter-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:type-parameter-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_type-parameter-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_type-parameter-comment = disabled\n
"},{"location":"rules/standard/#unnecessary-parenthesis-before-trailing-lambda","title":"Unnecessary parenthesis before trailing lambda","text":"

An empty parentheses block before a lambda is redundant.

Ktlint Disallowed
val foo = \"some-string\".count { it == '-' }\n
val foo = \"some-string\".count() { it == '-' }\n

Rule id: standard:unnecessary-parentheses-before-trailing-lambda

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:unnecessary-parentheses-before-trailing-lambda\")\n
    Enable rule via .editorconfig
    ktlint_standard_unnecessary-parentheses-before-trailing-lambda = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_unnecessary-parentheses-before-trailing-lambda = disabled\n
"},{"location":"rules/standard/#value-argument-comment","title":"Value argument comment","text":"

Disallows comments to be placed at certain locations inside a value argument.

Ktlint Disallowed
val foo1 =\n    foo(\n        /* some comment */\n        bar = \"bar\"\n    )\nval foo2 =\n    foo(\n        // some comment\n        bar = \"bar\"\n    )\n
val foo1 = foo(bar /* some comment */ = \"bar\")\nval foo2 = \n    foo(\n        bar = // some comment\n            \"bar\"\n    )\n

Rule id: standard:value-argument-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:value-argument-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_value-argument-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_value-argument-comment = disabled\n
"},{"location":"rules/standard/#value-parameter-comment","title":"Value parameter comment","text":"

Disallows comments to be placed at certain locations inside a value argument.

Ktlint Disallowed
class Foo1(\n    /** some kdoc */\n    bar = \"bar\"\n)\nclass Foo2(\n    /* some comment */\n    bar = \"bar\"\n)\nclass Foo3(\n    // some comment\n    bar = \"bar\"\n)\n
class Foo1(\n   bar = /** some kdoc */ \"bar\"\n)\nclass Foo2(\n   bar = /* some comment */ \"bar\"\n)\nclass Foo3(\n    bar =\n       // some comment\n       \"bar\"\n)\n

Rule id: standard:value-parameter-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:value-parameter-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_value-parameter-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_value-parameter-comment = disabled\n
"},{"location":"rules/standard/#wrapping","title":"Wrapping","text":""},{"location":"rules/standard/#argument-list-wrapping","title":"Argument list wrapping","text":"

All arguments should be on the same line, or every argument should be on a separate line.

Ktlint Disallowed
val foo =\n    foo(\n        a,\n        b,\n        c,\n    )\n
val foo =\n    foo(\n        a,\n        b, c,\n    )\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_argument_list_wrapping_ignore_when_parameter_count_greater_or_equal_than unset 8 8 max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:argument-list-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:argument-list-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_argument-list-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_argument-list-wrapping = disabled\n
"},{"location":"rules/standard/#chain-wrapping","title":"Chain wrapping","text":"

When wrapping chained calls ., ?. and ?: should be placed on the next line

Ktlint Disallowed
val foo =\n    listOf(1, 2, 3)\n        .filter { it > 2 }!!\n        .takeIf { it.count() > 100 }\n        ?.sum()\nval foobar =\n    foo()\n        ?: bar\n
val foo =\n    listOf(1, 2, 3).\n        filter { it > 2 }!!.\n        takeIf { it.count() > 100 }?.\n        sum()\nval foobar =\n    foo() ?:\n        bar\n

Rule id: standard:chain-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:chain-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_chain-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_chain-wrapping = disabled\n
"},{"location":"rules/standard/#comment-wrapping","title":"Comment wrapping","text":"

A block comment should start and end on a line that does not contain any other element.

Ktlint Disallowed
// Some comment 1\nval foo1 = \"foo1\"\nval foo2 = \"foo\" // Some comment\nval foo3 = { /* no-op */ } \n
/* Some comment 1 */ val foo1 = \"foo1\"\nval foo2 = \"foo\" /* Block comment instead of end-of-line comment */\nval foo3 = \"foo\" /* Some comment\n                  * with a newline\n                  */\n

Rule id: standard:comment-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:comment-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_comment-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_comment-wrapping = disabled\n
"},{"location":"rules/standard/#condition-wrapping","title":"Condition wrapping","text":"

Wraps each operand in a multiline condition to a separate line.

Ktlint Disallowed
val foo = bar || baz\nif (bar1 ||\n    bar2 ||\n    baz1 ||\n    (baz2 && baz3)\n) {\n   // do something\n}\n
val foo =\n  multiLineOperand(\n      \"bar\"\n  ) || baz\nif (bar1 || bar2 ||\n    baz1 || (baz2 && baz3)\n) {\n   // do something\n}\n

Rule id: standard:condition-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:condition-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_condition-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_condition-wrapping = disabled\n
"},{"location":"rules/standard/#content-receiver-wrapping","title":"Content receiver wrapping","text":"

Wraps the content receiver list to a separate line regardless of maximum line length. If the maximum line length is configured and is exceeded, wrap the context receivers and if needed its projection types to separate lines.

Ktlint Disallowed
// Always wrap regardless of whether max line length is set\ncontext(Foo)\nfun fooBar()\n\n// Wrap each context receiver to a separate line when the\n// entire context receiver list does not fit on a single line\ncontext(\n    Fooooooooooooooooooo1,\n    Foooooooooooooooooooooooooooooo2\n)\nfun fooBar()\n\n// Wrap each context receiver to a separate line when the\n// entire context receiver list does not fit on a single line.\n// Also, wrap each of it projection types in case a context\n// receiver does not fit on a single line after it has been\n// wrapped.\ncontext(\n    Foooooooooooooooo<\n        Foo,\n        Bar,\n        >\n)\nfun fooBar()\n
// Should be wrapped regardless of whether max line length is set\ncontext(Foo) fun fooBar()\n\n// Should be wrapped when the entire context receiver list does not\n// fit on a single line\ncontext(Fooooooooooooooooooo1, Foooooooooooooooooooooooooooooo2)\nfun fooBar()\n\n// Should be wrapped when the entire context receiver list does not\n// fit on a single line. Also, it should wrap each of it projection\n// type in case a context receiver does not fit on a single line \n// after it has been wrapped.\ncontext(Foooooooooooooooo<Foo, Bar>)\nfun fooBar()\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:context-receiver-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:context-receiver-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_context-receiver-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_context-receiver-wrapping = disabled\n
"},{"location":"rules/standard/#enum-wrapping","title":"Enum wrapping","text":"

An enum should be a single line, or each enum entry has to be placed on a separate line. In case the enumeration contains enum entries and declarations those are to be separated by a blank line.

Ktlint Disallowed
enum class Foo { A, B, C, D }\n\nenum class Foo {\n    A,\n    B,\n    C,\n    D,\n    ;\n\n    fun foo() = \"foo\"\n}\n
enum class Foo {\n    A,\n    B, C,\n    D\n}\n\nenum class Foo {\n    A;\n    fun foo() = \"foo\"\n}\n

Rule id: standard:enum-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:enum-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_enum-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_enum-wrapping = disabled\n
"},{"location":"rules/standard/#if-else-wrapping","title":"If else wrapping","text":"

A single line if-statement should be kept simple. It may contain no more than one else-branch. The branches may not be wrapped in a block.

Ktlint Disallowed
fun foobar() {\n    if (true) foo()\n    if (true) foo() else bar()\n}\n
fun foobar() {\n    if (true) if (false) foo() else bar()\n    if (true) bar() else if (false) foo() else bar()\n    if (true) { foo() } else bar()\n    if (true) bar() else { if (false) foo() else bar() }\n}\n

Rule id: standard:if-else-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:if-else-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_if-else-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_if-else-wrapping = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#multiline-expression-wrapping","title":"Multiline expression wrapping","text":"

Multiline expression on the right hand side of an expression are forced to start on a separate line. Expressions in return statement are excluded as that would result in a compilation error.

Setting ktlint_function_signature_body_expression_wrapping of the function-signature rule takes precedence when set to default. This setting keeps the first line of a multiline expression body on the same line as the end of function signature as long as the max line length is not exceeded. In that case, this rule does not wrap the multiline expression.

Ktlint Disallowed
val foo =\n    foo(\n        parameterName =\n            \"The quick brown fox \"\n                .plus(\"jumps \")\n                .plus(\"over the lazy dog\"),\n    )\n
val foo = foo(\n    parameterName = \"The quick brown fox \"\n        .plus(\"jumps \")\n        .plus(\"over the lazy dog\"),\n)\n

Rule id: standard:multiline-expression-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:multiline-expression-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_multiline-expression-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_multiline-expression-wrapping = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#parameter-list-wrapping","title":"Parameter list wrapping","text":"

When class/function signature doesn't fit on a single line, each parameter must be on a separate line.

Note

Wrapping of parameters is also influenced by the function-signature rule.

Ktlint Disallowed (ktlint_official) Disallowed (non ktlint_official)\"
// If `ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than` equals\n// `unset` the parameters are not wrapped as long as they fit on a single line\nclass ClassA(paramA: String, paramB: String, paramC: String)\n\nclass ClassA(\n    paramA: String,\n    paramB: String,\n    paramC: String\n)\n\n// If `ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than` equals\n// `unset` the parameters are not wrapped as long as they fit on a single line\nfun f(a: Any, b: Any, c: Any)\n\nfun f(\n    a: Any,\n    b: Any,\n    c: Any\n)\n\nfun foo(\n    @Bar fooBar: FooBar\n)\n
class ClassA(\n    paramA: String, paramB: String,\n    paramC: String\n)\n\nfun f(\n    a: Any,\n    b: Any, c: Any\n)\n\nfun foo(@Bar fooBar: FooBar)\n
class ClassA(\n    paramA: String, paramB: String,\n    paramC: String\n)\n\nfun f(\n    a: Any,\n    b: Any, c: Any\n)\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:parameter-list-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:parameter-list-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_parameter-list-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_parameter-list-wrapping = disabled\n
"},{"location":"rules/standard/#parameter-wrapping","title":"Parameter wrapping","text":"

When a function or class parameter doesn't fit on a single line, wrap the type or value to a separate line

Ktlint (ktlint_official) Ktlint (non ktlint_official) Disallowed
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Bar(\n    val fooooooooooooooooooooooooTooLong:\n        Foo,\n)\n\nfun bar(\n    fooooooooooooooooooooooooTooLong:\n        Foo,\n)\n
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Bar(\n    val fooooooooooooooooooooooooTooLong:\n    Foo,\n)\n\nfun bar(\n    fooooooooooooooooooooooooTooLong:\n    Foo,\n)\n
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Bar(\n    val fooooooooooooooooooooooooTooLong: Foo,\n)\n\nfun bar(\n    fooooooooooooooooooooooooooooTooLong: Foo,\n)\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:parameter-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:parameter-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_parameter-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_parameter-wrapping = disabled\n
"},{"location":"rules/standard/#property-wrapping","title":"Property wrapping","text":"

When a property doesn't fit on a single line, wrap the type or value to a separate line

Ktlint Disallowed
// Assume that the last allowed character is\n// at the X character on the right           X\nval aVariableWithALooooooooooooongName:\n    String\n
// Assume that the last allowed character is\n// at the X character on the right           X\nval aVariableWithALooooooooooooongName: String\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:property-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:property-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_property-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_property-wrapping = disabled\n
"},{"location":"rules/standard/#statement-wrapping","title":"Statement wrapping","text":"

A function, class/object body or other block body statement has to be placed on different line than the braces of the body block.

Ktlint Disallowed
fun foo() {\n    if (true) {\n        // do something\n    }\n}\n\nclass A {\n    val a = 0\n    val b = 1\n}\n\nenum class FooBar1 { FOO, BAR }\n\nenum class FooBar2 {\n    FOO,\n    BAR,\n}\n
fun foo() { if (true) {\n        // do something\n    }\n}\n\nclass A { val a = 0\n    val b = 1 }\n

Rule id: standard:statement-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:statement-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_statement-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_statement-wrapping = disabled\n
"},{"location":"rules/standard/#wrapping_1","title":"Wrapping","text":"

Inserts missing newlines (for example between parentheses of a multi-line function call).

Ktlint Disallowed
val foo =\n    foo(\n        a,\n        b,\n        c,\n    )\n
val foo = foo(\n    a,\n    b,\n    c)\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_wrapping = disabled\n
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome to Ktlint","text":"

Kotlin linter in spirit of feross/standard (JavaScript) and gofmt (Go).

"},{"location":"#features","title":"Features","text":""},{"location":"#legal","title":"Legal","text":"

This project is not affiliated with nor endorsed by JetBrains. All code, unless specified otherwise, is licensed under the MIT license. Copyright \u00a9 2019 Pinterest, Inc. Copyright \u00a9 2016-2019 Stanley Shyiko.

"},{"location":"faq/","title":"FAQ","text":""},{"location":"faq/#why-should-i-use-ktlint","title":"Why should I use ktlint?","text":"

the short answer is Simplicity.

Spending time on configuration (and maintenance down the road) of hundred-line long style config file(s) is counter-productive. Instead of wasting your energy on something that has no business value - focus on what really matters (not debating whether to use tabs or spaces).

By using ktlint you put the importance of code clarity and community conventions over personal preferences. This makes things easier for people reading your code as well as frees you from having to document and explain what style potential contributor(s) have to follow.

ktlint is a single binary with both linter & formatter included. All you need is to drop it in (no need to get overwhelmed while choosing among dozens of code style options).

"},{"location":"faq/#what-are-the-maven-coordinates-in-ktlint-1x","title":"What are the Maven coordinates in Ktlint 1.x?","text":"

With the release of ktlint 1.0 the Maven coordinates of most modules have been changed. Now all ktlint modules are published in Maven group com.pinterest.ktlint. Also, the artifact id's of some modules have been changed.

The Maven coordinates of modules below have been changed:

Old Maven coordinates New Maven coordinates com.pinterest:ktlint com.pinterest.ktlint:ktlint-cli com.pinterest.ktlint:ktlint-reporter-baseline com.pinterest.ktlint:ktlint-cli-reporter-baseline com.pinterest.ktlint:ktlint-reporter-checkstyle com.pinterest.ktlint:ktlint-cli-reporter-checkstyle com.pinterest.ktlint:ktlint-cli-reporter com.pinterest.ktlint:ktlint-cli-reporter-core com.pinterest.ktlint:ktlint-reporter-format com.pinterest.ktlint:ktlint-cli-reporter-format com.pinterest.ktlint:ktlint-reporter-html com.pinterest.ktlint:ktlint-cli-reporter-html com.pinterest.ktlint:ktlint-reporter-json com.pinterest.ktlint:ktlint-cli-reporter-json com.pinterest.ktlint:ktlint-reporter-plain com.pinterest.ktlint:ktlint-cli-reporter-plain com.pinterest.ktlint:ktlint-reporter-plain-summary com.pinterest.ktlint:ktlint-cli-reporter-plain-summary com.pinterest.ktlint:ktlint-reporter-sarif com.pinterest.ktlint:ktlint-cli-reporter-sarif"},{"location":"faq/#how-do-i-enable-or-disable-a-rule","title":"How do I enable or disable a rule?","text":"

An individual rule can be enabled or disabled with a rule property. The name of the rule property consists of the ktlint_ prefix followed by the rule set id followed by a _ and the rule id. Examples:

ktlint_standard_final-newline = disabled # Disables the `final-newline` rule in the `standard` rule set provided by KtLint\nktlint_standard_some-experimental-rule = enabled # Enables the (experimental) `some-experimental-rule` in the `standard` rule set provided by KtLint\nktlint_custom-rule-set_custom-rule = disabled # Disables the `custom-rule` rule in the `custom-rule-set` rule set (not provided by KtLint)\n

Note

The rule properties are applied after applying the rule set properties and take precedence. So if a rule set is disabled but a specific rule of that rule set is enabled, then the rule will be executed.

"},{"location":"faq/#how-do-i-enable-or-disable-a-rule-set","title":"How do I enable or disable a rule set?","text":"

All rules in a rule set can be enabled or disabled with a rule set property. The name of the rule set property consists of the ktlint_ prefix followed by the rule set id. Examples:

ktlint_standard = disabled # Disable all rules from the `standard` rule set provided by KtLint\nktlint_experimental = enabled # Enable rules marked as experimental for all rule sets that are enabled\nktlint_custom-rule-set = enabled # Enable all rules in the `custom-rule-set` rule set (not provided by KtLint)\n

Note

All rules from the standard and custom rule sets are enabled by default and can optionally be disabled in the .editorconfig. All experimental rules are disabled by default and can optionally be enabled in the .editorconfig.

"},{"location":"faq/#why-is-a-rule-skipped-when-i-disable-some-other-rule","title":"Why is a rule skipped when I disable some other rule?","text":"

Most rules in ktlint can be executed independently of other rules. However, some rules can only be executed in case one or more other rules are also loaded and/or enabled. Dependencies between rules are introduced to reduce complexity in ktlint. Similar logic in different rules has to be avoided as this might result in formatting conflicts between different rules, which could result in endless loops of formatting and reformatting by a set of rules.

In case, you disable a rule, you might run into an IllegalStateException like below:

java.lang.IllegalStateException: Skipping rule(s) which are depending on a rule which is not loaded. Please check if you need to add additional rule sets before creating an issue.\n  - Rule with id 'RuleId(value=standard:string-template-indent)' requires rule with id 'RuleId(value=standard:multiline-expression-wrapping)' to be loaded\n

For the example above, the string-template-indent rule depends on the multiline-expression-wrapping so that the former rule does not need to know, how to wrap a multiline string that is not yet wrapped:

val foo = \"\"\"\n    some text\n   \"\"\".trimIndent()\n

"},{"location":"faq/#why-does-ktlint-discourage-certain-comment-locations","title":"Why does ktlint discourage certain comment locations?","text":"

Kotlin has three different type of comments. Although the KDoc and the block comment look similar in code, their internal PSI structure is different. The EOL comment is yet very different.

In Kotlin it is possible to insert a comment everywhere. It is very challenging, and time-consuming, to make each rule fully resilient for each possible comment location, even in case such locations will (almost) never by used.

For example, in sample below it is unclear whether the comment applies to the if block, or to the else block without interpreting the comment itself.

Unclear comment Clear comment
if (someCondition) {\n    doTrue()\n} // comment\nelse {\n    doFalse()\n}\n
if (someCondition) {\n    doTrue()\n} else { \n    // comment\n    doFalse()\n}\n

In other cases, a comment location is more widely used but semantically still incorrect. For example, in sample below the EOL comment is placed after the comma, but it obviously is related to the part before the comma:

Unclear comment Clear comment
fun fooBar(\n    foo: Foo, // foo-comment\n    bar: Bar, // bar-comment\n) {}\n
fun fooBar(\n    // foo-comment\n    foo: Foo,\n    // bar-comment\n    bar: Bar,\n) {}\n

By forbidding certain comment locations, the logic in the rules becomes a bit easier.

"},{"location":"faq/#can-i-have-my-own-rules-on-top-of-ktlint","title":"Can I have my own rules on top of ktlint?","text":"

Absolutely, \"no configuration\" doesn't mean \"no extensibility\". You can add your own ruleset(s) to discover potential bugs, check for anti-patterns, etc.

See adding a custom rule set for more information.

"},{"location":"faq/#how-do-i-suppress-errors-for-a-lineblockfile","title":"How do I suppress errors for a line/block/file?","text":"

Tip

Suppressing a ktlint violation is meant primarily as an escape latch for the rare cases when ktlint is not able to produce the correct result. Please report any such instances using GitHub Issues).

To disable a specific rule you'll need the fully qualified rule identifier. This identifier is displayed at the end of the lint error. In case your code was autocorrected, you need to revert the code and run the lint task instead of the format to find the rule identifier.

As of Ktlint 0.50, an error can only be suppressed using @Suppress or @SuppressWarnings annotations

Warning

Import statements can not be annotated in Kotlin. The rules related to import statements can be suppressed with file annotations only.

Allowed
// Suppressing all rules for the entire file\n@file:Suppress(\"ktlint\")\n\n// Suppressing specific rules for the entire file\n// Rules related to import statements can only be suppressed using file annotations\n@file:Suppress(\"ktlint:standard:no-wildcard-imports\", \"ktlint:custom-rule-set-id:custom-rule-id\")\n\n// Suppress all rules for the annotated construct\n@Suppress(\"ktlint\")\nclass Foo {}\n\n// Suppress a single rule (with id 'rule-id', defined in rule set with id 'rule-set-id') in the scope of the annotated construct\n@Suppress(\"ktlint:rule-set-id:rule-id\")\nclass Foo {}\n
"},{"location":"faq/#why-is-editorconfig-property-disabled_rules-deprecated-and-how-do-i-resolve-this","title":"Why is .editorconfig property disabled_rules deprecated and how do I resolve this?","text":"

The .editorconfig properties disabled_rules and ktlint_disabled_rules are deprecated as of KtLint version 0.48 and are removed in version 0.49. Those properties contain a comma separated list of rules which are disabled. Using a comma separated list of values has some disadvantages.

A big disadvantage is that it is not possible to override the property partially in an .editorconfig file in a subpackage. Another disadvantage is that it is not possible to express explicitly that a rule is enabled. Lastly, (qualified) rule ids can be 20 characters or longer, which makes a list with multiple entries hard to read.

Starting with KtLint 0.48 entire rule sets and individual rules can be disabled / enabled with a separate property per rule (set). Examples:

ktlint_standard = disabled # Disable all rules from the `standard` rule set provided by KtLint\nktlint_standard_final-newline = enabled # Enables the `final-newline` rule in the `standard` rule set provided by KtLint\nktlint_experimental = enabled # Enable rules marked as experimental for all rule sets that are enabled\nktlint_standard_some-experimental-rule = disabled # Disables the (experimental) `some-experimental-rule` in the `standard` rule set provided by KtLint\nktlint_custom-rule-set = enabled # Enable all rules in the `custom-rule-set` rule set (not provided by KtLint)\nktlint_custom-rule-set_custom-rule = disabled # Disables the `custom-rule` rule in the `custom-rule-set` rule set (not provided by KtLint)\n

Note

All rules from the standard and custom rule sets are enabled by default and can optionally be disabled in the .editorconfig. All experimental rules are disabled by default and can optionally be enabled in the .editorconfig.

Note

The rule properties are applied after applying the rule set properties and take precedence. So if a rule set is disabled but a specific rule of that rule set is enabled, then the rule will be executed.

"},{"location":"faq/#why-is-wildcard-import-javautil-not-reported-by-the-no-wildcard-imports-rule","title":"Why is wildcard import java.util.* not reported by the no-wildcard-imports rule?","text":"

The no-wildcard-imports rule forbids wildcard imports, except for imports defined in .editorconfig property ij_kotlin_packages_to_use_import_on_demand. If this property is not explicitly set, it allows wildcards imports like java.util.* by default to keep in sync with IntelliJ IDEA behavior.

"},{"location":"faq/#can-a-new-toggle-be-added-to-optionally-enabledisable-format-code-in-a-particular-way","title":"Can a new toggle be added to optionally (enable/disable) format code in a particular way?","text":"

Ktlint can be configured by enabling and disabling rules. Some rules can be configured in more details with additional .editorconfig properties. Regularly, a new configuration option is requested to modify behavior in existing rules.

Ktlint is restrictive with adding additional configuration settings to customize behavior in rules. Each configuration option that Ktlint offers comes with complexity that has to be maintained by only a couple of maintainers. As of that, we cannot provide tens or even hundreds of such options.

Less configuration options also means less discussions in teams about settings to use. Unfortunately this means that you cannot tweak Ktlint exactly to the format you prefer.

Tip

Any idea for a new configuration option is valuable. Please create an issue for it so that it can be considered to incorporate it in Ktlint.

"},{"location":"faq/#can-i-use-ktlint-to-directly-format-the-code-im-generating-with-kotlinpoet","title":"Can I use KtLint to directly format the code I'm generating with KotlinPoet?","text":"

Yes, it is possible to use KtLint to directly format the code generated with KotlinPoet. To do so, you must include the dependencies com.pinterest.ktlint:ktlint-core and com.pinterest.ktlint:ktlint-ruleset-standard in your Gradle/Maven project.

Warning

Do not include the dependency com.pinterest.ktlint:ktlint-cli as that would import the entire ktlint project including unwanted dependencies. Besides a much bigger artifact, it might also result in problems regarding logging.

To format the output of KotlinPoet with KtLint, you can use the following snippet:

val ruleProviders = buildSet {\n  ServiceLoader\n      .load(RuleSetProviderV2::class.java)\n      .flatMapTo(this) { it.getRuleProviders() }\n}\nval ktLintRuleEngine = KtLintRuleEngine(\n  ruleProviders = ruleProviders,\n  editorConfigDefaults = EditorConfigDefaults.load(EDITORCONFIG_PATH),\n)\nktLintRuleEngine.format(outputDir.toPath())\n
Here, outputDir refers to the directory of the generated files by KotlinPoet, ktLintRuleEngine is an instance of KtLint rule engine.

It is also possible to format file-by-file the output of KotlinPoet if you write your FileSpec to a StringBuilder(), instead of a File, and send the generated code as String to KtLint inside a CodeSnippet:

kotlinFile.writeText(\n  ktLintRuleEngine.format(\n    Code.CodeSnippet(\n      stringBuilder.toString()\n    )\n  )\n)\n

"},{"location":"faq/#are-formatter-tags-respected","title":"Are formatter tags respected?","text":"

As of version 0.49.x the formatter tags of IntelliJ IDEA are respected. By default, those formatter tags are disabled. The formatter tags can be enabled with .editorconfig properties below:

ij_formatter_tags_enabled = true # Defaults to 'false'\nij_formatter_off_tag = some-custom-off-tag # Defaults to '@formatter:off'\nij_formatter_on_tag = some-custom-on-tag # Defaults to '@formatter:on'\n

When enabled, the ktlint rule checking is disabled for all code surrounded by the formatter tags.

"},{"location":"faq/#how-do-i-disable-ktlint-for-generated-code","title":"How do I disable ktlint for generated code?","text":"

Running ktlint on generated code is not useful. Fixing lint and format errors on generated code is a waste of time as errors will be re-introduced once that code is generated again. Given that generated code is located in a separate directory, you can disable ktlint for such directory by adding a glob for that directory:

[some/path/to/generated/code/**/*]\nktlint = disabled\n

Warning

The ec4j library used by ktlint does not seem to work with globs starting with ** followed by a chain of multiple directories (for example **/path/to/generated/**/*). But both some/path/to/generated/**/* and **/generated/**/* work fine.

"},{"location":"quick-start/","title":"Quick start","text":"

Follow steps below for a quick start with latest ktlint release.

"},{"location":"quick-start/#step-1-install-with-brew","title":"Step 1: Install with brew","text":"

brew install ktlint\n
See download and verification from GitHub or other package managers for alternative ways of installing ktlint. Or, use one of the integrations like maven and gradle plugins.

"},{"location":"quick-start/#step-2-lint-and-format-your-code","title":"Step 2: Lint and format your code","text":"

All files with extension .kt and .kts in the current directory and below will be scanned. Problems will be fixed automatically when possible. Autocorrect style violations

ktlint --format\n# or\nktlint -F\n
See cli usage for a more extensive description on using ktlint.

"},{"location":"readme/","title":"Build & test documentation on local machine","text":"

The documentation of ktlint is served with mkdocs-material. For full documentation visit mkdocs.org.

To build and test documentation on your local development machine, follow steps below:

"},{"location":"readme/#setup","title":"Setup","text":"
  1. In IntelliJ IDEA
  2. Pull docker image
    $ docker pull squidfunk/mkdocs-material\n
"},{"location":"readme/#build-server","title":"Build server","text":"

The following steps build and host the documentation locally, updating automatically whenever a local file is changed.

  1. Start mkdocs server from root of project (e.g. from same directory where file mkdocs.yml is located)
    docker run --rm -it -p 8000:8000 -v ${PWD}:/docs squidfunk/mkdocs-material\n
  2. Visit page http://0.0.0.0:8000/ in your browser.
  3. Edit the documentation and explicitly save the file. The mkdocs server refreshes its cached and the current page in the browser is automatically refreshed.
"},{"location":"readme/#build-once","title":"Build once","text":"

If you do not want to run a local server, or if you want to inspect the built files, you can run the following command from the project's main directory to build the documentation in the site/ directory.

docker run --rm -it -p 8000:8000 -v ${PWD}:/docs squidfunk/mkdocs-material build\n
"},{"location":"api/badge/","title":"Badge","text":"

If you want to display a badge to show that your project is linted and formatted using 'ktlint than you can add the badge:

Ktlint code style badge
[![ktlint](https://img.shields.io/badge/ktlint%20code--style-%E2%9D%A4-FF4081)](https://pinterest.github.io/ktlint/)\n
"},{"location":"api/custom-integration/","title":"Custom integration","text":""},{"location":"api/custom-integration/#ktlint-rule-engine","title":"Ktlint Rule Engine","text":"

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 =\n  KtLintRuleEngine(\n    ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,\n  )\n
"},{"location":"api/custom-integration/#rule-provider","title":"Rule provider","text":"

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 your own custom rules, or a combination of both. Creating a set of RuleProviders

val KTLINT_API_CONSUMER_RULE_PROVIDERS =\n  setOf(\n    // Can provide custom rules\n    RuleProvider { NoVarRule() },\n    // but also reuse rules from KtLint rulesets\n    RuleProvider { IndentationRule() },\n  )\n

"},{"location":"api/custom-integration/#editor-config-defaults-overrides","title":"Editor config: defaults & overrides","text":"

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 =\n  KtLintRuleEngine(\n    ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,\n    editorConfigOverride = EditorConfigOverride.from(\n      INDENT_STYLE_PROPERTY to IndentConfig.IndentStyle.SPACE,\n      INDENT_SIZE_PROPERTY to 4\n    )\n  )\n

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 =\n  KtLintRuleEngine(\n    ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,\n    editorConfigDefaults = EditorConfigDefaults.load(\n      path = Paths.get(\"/some/path/to/editorconfig/file/or/directory\"),\n      propertyTypes = KTLINT_API_CONSUMER_RULE_PROVIDERS.propertyTypes(),\n    )\n  )\n
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 =\n  KtLintRuleEngine(\n    ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS,\n    editorConfigDefaults = EditorConfigDefaults(\n      org.ec4j.core.model.EditorConfig\n        .builder()\n        // .. add relevant properties\n        .build()\n    )\n  )\n
"},{"location":"api/custom-integration/#lint-format","title":"Lint & format","text":"

Once the KtLintRuleEngine has been defined, it is ready to be invoked for code that has to be linted or formatted. 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(\n    File(\"/some/path/to/file\")\n)\n
or a code snippet (set script to true to handle the snippet as Kotlin script): Code from snippet
val code = Code.fromSnippet(\n    \"\"\"\n    val code = \"some-code\"\n    \"\"\".trimIndent()\n)\n

The lint function is invoked with an optional lambda. Once linting is complete, the lambda will be called for each LintError which is found. Invoking lint

ktLintRuleEngine\n    .lint(code) { lintError ->\n        // handle\n    }\n

The format function is invoked with a lambda. The lambda is called for each LintError which is found. If the LintError can be autocorrected, the return value of the lambda instructs the rule whether this specific LintError is to be autocorrected, or not. If the LintError can not be autocorrected, the return result of the lambda is ignored. The formatted code is returned as result of the function.

The new format function allows the API Consumer to decide which LintError is to be autocorrected, or not. This is most interesting for API Consumers that let their user interactively decide per LintError how it has to be handled. For example see the ktlint-intellij-plugin which in 'manual' mode displays all lint violations, which allows the user to decide which LintError is to be autocorrected.

Note

The difference with the legacy version of the format is subtle. It takes two parameters (a LintError and Boolean denoting whether the LintError is corrected), and it does not return a value.

Invoke format (preferred, starting from Ktlint 1.3)
val formattedCode =\n    ktLintRuleEngine\n      .format(code) { lintError ->\n          if (lintError.canBeAutoCorrected) {\n              // Return AutocorrectDecision.ALLOW_AUTOCORRECT to execute the autocorrect of this lintError if this is supported by the rule.\n              // Return AutocorrectDecision.NO_AUTOCORRECT if the LintError should not be corrected even if is supported by the rule.\n          } else {\n              // In case the LintError can not be autocorrected, the return value of the lambda will be ignored.\n              // For clarity reasons it is advised to return AutocorrectDecision.NO_AUTOCORRECT in case the LintError can not be autocorrected.\n              AutocorrectDecision.NO_AUTOCORRECT\n          }\n      }\n

Warning

Rules need to implement the interface RuleAutocorrectApproveHandler in order to let the API Consumer decide whether a LintError is to be autocorrected, or not. This interface is implemented for all rules provided via the Ktlint project starting from version 1.3. However, external rulesets may not have implemented this interface on their rulesets though. Contact the maintainer of such a ruleset to implement this interface.

The (legacy) format function is invoked with an optional lambda. Once formatting is complete, the lambda will be called for each LintError which is found. The (legacy) format function fixes all LintErrors for which an autocorrect is available. The formatted code is returned as result of the function.

Invoke format (deprecated as of Ktlint 1.3, will be removed in Ktlint 2.0)
// Up until Ktlint 1.2.1 the format was invoked with a lambda having two parameters and not returning a result. This function will be removed in Ktlint 2.0 \nval formattedCode =\n    ktLintRuleEngine\n        .format(code) { lintError, corrected ->\n            // handle\n        }\n
"},{"location":"api/custom-integration/#rule-ruleautocorrectapprovehandler","title":"Rule & RuleAutocorrectApproveHandler","text":"

Note

Providers of custom rules are strongly encouraged to implement RuleAutocorrectApproveHandler interface as described below. The ktlint-intellij-plugin, which will be updated soon after the 1.3 release of Ktlint, make use of this new functionality. If your ruleset is used by users of the plugin, it is very likely that they want to be able to autocorrect individual LintErrors or to format a block of code (e.g. a selection) in a file. This functionality will only be available for rules that have implemented this interface.

In Ktlint 1.3 the RuleAutocorrectApproveHandler interface is added. This interface adds the ability that the API Consumer decides per LintError whether it needs to autocorrected, or not. In Ktlint 2.0 the methods beforeVisitChildNodes and afterVisitChildNodes of the Rule class will be replaced with the new versions which are now added to the RuleAutocorrectApproveHandler interface as is shown below (the signature for afterVisitChildNodes is changed similarly):

Deprecated signature in `Rule` class
public open fun beforeVisitChildNodes(\n    node: ASTNode,\n    autoCorrect: Boolean,\n    emit: (\n        offset: Int,\n        errorMessage: String,\n        canBeAutoCorrected: Boolean\n    ) -> Unit,\n)  \n
New signature in `RuleAutocorrectApproveHandler` interface
public fun beforeVisitChildNodes(\n    node: ASTNode,\n    emit: (\n        offset: Int,\n        errorMessage: String,\n        canBeAutoCorrected: Boolean\n    ) -> AutocorrectDecision,\n)\n

The autoCorrect parameter is no longer passed to the method. Instead, the emit lambda now returns the value AutocorrectDecision.ALLOW_AUTOCORRECT or AutocorrectDecision.NO_AUTOCORRECT.

In case a LintError is detected, and can be autocorrected, the LintError can be processed as shown below:

emit(node.startOffset, \"some detail message\", true)\n   .ifAutocorrectAllowed {\n       // Autocorrect the LintError\n   }\n

In case the LintError can not be autocorrected, if suffices to emit the violation only:

emit(node.startOffset, \"some detail message\", false)\n

"},{"location":"api/custom-integration/#logging","title":"Logging","text":"

Ktlint uses the io.github.oshai: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.

"},{"location":"api/custom-reporter/","title":"Custom reporter","text":""},{"location":"api/custom-reporter/#build-a-custom-reporter","title":"Build a custom reporter","text":"

Take a look at ktlint-cli-reporter-plain.

In short, all you need to do is to implement a ReporterV2 and make it available by registering a custom ReporterProviderV2 using META-INF/services/com.pinterest.ktlint.cli.reporter.core.api.ReporterProviderV2. Pack all of that into a JAR and you're done.

To load a custom (3rd party) reporter use ktlint --reporter=name,artifact=/path/to/custom-ktlint-reporter.jar (see ktlint --help for more).

"},{"location":"api/custom-reporter/#third-party-reporters","title":"Third party reporters","text":"

Known third-party reporters:

"},{"location":"api/custom-rule-set/","title":"Custom rule set","text":"

Tip

See Writing your first ktlint rule by Niklas Baudy.

In a nutshell: a \"rule set\" is a JAR containing one or more Rules. ktlint is relying on the ServiceLoader to discover all available \"RuleSet\"s on the classpath. As a ruleset author, all you need to do is to include a META-INF/services/RuleSetProviderV3 file containing a fully qualified name of your RuleSetProviderV3 implementation.

"},{"location":"api/custom-rule-set/#ktlint-ruleset-template","title":"ktlint-ruleset-template","text":"

A complete sample project (with tests and build files) is included in this repo under the ktlint-ruleset-template directory (make sure to check NoVarRuleTest as it contains some useful information).

Building the ktlint-ruleset-template
$ cd ktlint-ruleset-template/\n$ ../gradlew build\n
Provide code sample that violates rule `custom:no-var
$ echo 'var v = 0' > test.kt\n
Running the ktlint-ruleset-template
$ ktlint -R build/libs/ktlint-ruleset-template.jar --log-level=debug --relative test.kt\n\n18:13:21.026 [main] DEBUG com.pinterest.ktlint.internal.RuleSetsLoader - JAR ruleset provided with path \"/../ktlint/ktlint-ruleset-template/build/libs/ktlint-ruleset-template.jar\"\n18:13:21.241 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"baseline\" id.\n18:13:21.241 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"checkstyle\" id.\n18:13:21.241 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"json\" id.\n18:13:21.242 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"html\" id.\n18:13:21.242 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"plain\" id.\n18:13:21.242 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with \"sarif\" id.\n18:13:21.242 [main] DEBUG com.pinterest.ktlint.Main - Initializing \"plain\" reporter with {verbose=false, color=false, color_name=DARK_GRAY}\n[DEBUG] Rule with id 'standard:max-line-length' should run after the rule with id 'trailing-comma'. However, the latter rule is not loaded and is allowed to be ignored. For best results, it is advised load the rule.\n[DEBUG] Rules will be executed in order below (unless disabled):\n           - standard:filename, \n           - standard:final-newline, \n           - standard:chain-wrapping, \n           - standard:colon-spacing, \n           - standard:comma-spacing, \n           - standard:comment-spacing, \n           - standard:curly-spacing, \n           - standard:dot-spacing, \n           - standard:import-ordering, \n           - standard:keyword-spacing, \n           - standard:modifier-order, \n           - standard:no-blank-line-before-rbrace, \n           - standard:no-consecutive-blank-lines, \n           - standard:no-empty-class-body, \n           - standard:no-line-break-after-else, \n           - standard:no-line-break-before-assignment, \n           - standard:no-multi-spaces, \n           - standard:no-semi, \n           - standard:no-trailing-spaces, \n           - standard:no-unit-return, \n           - standard:no-unused-imports, \n           - standard:no-wildcard-imports, \n           - standard:op-spacing, \n           - standard:parameter-list-wrapping, \n           - standard:paren-spacing, \n           - standard:range-spacing, \n           - standard:string-template, \n           - custom:no-var, \n           - standard:indent, \n           - standard:max-line-length\n`text test.kt:1:1: Unexpected var, use val instead (cannot be auto-corrected)`\n18:13:21.893 [main] DEBUG com.pinterest.ktlint.Main - 872ms / 1 file(s) / 1 error(s)\n

Tip

Multiple custom rule sets can be loaded at the same time.

"},{"location":"api/custom-rule-set/#abstract-syntax-tree-ast","title":"Abstract Syntax Tree (AST)","text":"

While writing/debugging Rules it's often helpful to inspect the Abstract Syntax Tree (AST) of the code snippet that is to be linted / formatted. The Jetbrain PsiViewer plugin for IntelliJ IDEA is a convenient tool to inspect code as shown below:

"},{"location":"api/overview/","title":"Overview","text":"

Ktlint has an open API with which you can integrate.

The diagram below show the internal module structure of KtLint.

The Ktlint Rule Engine is by far the most important module. It is responsible for executing the linting and formatting of the source code. The Rule Engine itself does not contain any rules. Rules are provided by API Consumers.

The Ktlint CLI is an API Consumer of the Ktlint Rule Engine. Together with the Ktlint Ruleset Standard and the Ktlint Reporter modules the CLI offers a standalone tool which can easily be run from the commandline. Also, the Ktlint CLI can easily be used with custom rulesets and/or reporters.

The Ktlint Ruleset Core module contains the logic which is required by each API Consumer of the Ktlint Rule Engine, the Ktlint Ruleset Standard and custom rulesets.

The module Ktlint Test provide functionalities like assertThatRule which is used to write unit tests in a fluent AssertJ look-a-like style and can also be used for testing of custom rules.

The Ktlint logger module provides functionality for writing log messages.

"},{"location":"contributing/","title":"Index","text":""},{"location":"contributing/#contributing-guidelines","title":"Contributing guidelines","text":""},{"location":"contributing/code-of-conduct/","title":"Code of conduct","text":"

At Pinterest, we work hard to ensure that our work environment is welcoming and inclusive to as many people as possible. We are committed to creating this environment for everyone involved in our open source projects as well. We welcome all participants regardless of ability, age, ethnicity, identified gender, religion (or lack there of), sexual orientation and socioeconomic status.

This code of conduct details our expectations for upholding these values.

"},{"location":"contributing/code-of-conduct/#good-behavior","title":"Good behavior","text":"

We expect members of our community to exhibit good behavior including (but of course not limited to):

"},{"location":"contributing/code-of-conduct/#unacceptable-behavior","title":"Unacceptable behavior","text":"

Some examples of unacceptable behavior (again, this is not an exhaustive list):

"},{"location":"contributing/code-of-conduct/#recourse","title":"Recourse","text":"

If you are witness to or the target of unacceptable behavior, it should be reported to Pinterest at opensource-policy@pinterest.com. All reporters will be kept confidential and an appropriate response for each incident will be evaluated.

If the maintainers do not uphold and enforce this code of conduct in good faith, community leadership will hold them accountable.

"},{"location":"contributing/guidelines/","title":"Guidelines","text":"

First off, thanks for taking the time to contribute! This guide will answer some common questions about how this project works.

While this is a Pinterest open source project, we welcome contributions from everyone. Regular outside contributors can become project maintainers.

"},{"location":"contributing/guidelines/#help","title":"Help","text":"

If you're having trouble using this project, please start by reading all documentation and searching for solutions in the existing open and closed issues.

"},{"location":"contributing/guidelines/#security","title":"Security","text":"

If you've found a security issue in one of our open source projects, please report it at Bugcrowd; you may even make some money!

"},{"location":"contributing/guidelines/#code-of-conduct","title":"Code of Conduct","text":"

Please be sure to read and understand our code of conduct. We work hard to ensure that our projects are welcoming and inclusive to as many people as possible.

"},{"location":"contributing/guidelines/#reporting-issues","title":"Reporting Issues","text":"

If you have a bug report, please provide as much information as possible so that we can help you out:

"},{"location":"contributing/guidelines/#making-changes","title":"Making Changes","text":"

Tip

ktlint only provides rules that enforce the Kotlin coding conventions or Android Kotlin style guide. If your change is more opinionated than please file an issue first so that it can be discussed amongst the community. Rules which are too opinionated might be better published as a custom rule set.

  1. Fork this repository to your own account
  2. Make your changes and verify that tests pass
  3. Commit your work and push to a new branch on your fork
  4. Submit a pull request
  5. Participate in the code review process by responding to feedback

Once there is agreement that the code is in good shape, one of the project's maintainers will merge your contribution.

To increase the chances that your pull request will be accepted:

New rules have to implement the Rule.Experimental interface so that the rule will only be run for user who have opted in to use experimental rules. Once the rule is stable, the marker interface Rule.Experimental can be removed.

"},{"location":"contributing/guidelines/#updating-dependencies","title":"Updating dependencies","text":"

This project has enabled Gradle dependencies verification. On adding/updating any dependency, ensure that you've added dependency provided checksum/signature to gradle/verification-metadata.xml file.

"},{"location":"contributing/guidelines/#using-kotlin-development-versions","title":"Using kotlin development versions","text":"

Add following flag - -PkotlinDev to enable kotlin development version.

"},{"location":"contributing/guidelines/#license","title":"License","text":"

By contributing to this project, you agree that your contributions will be licensed under its license.

"},{"location":"contributing/overview/","title":"Overview","text":"

Important

Make sure to read the Contributing guideline and the code of conduct first.

"},{"location":"contributing/overview/#development","title":"Development","text":"

Development starts with cloning and building the project on your local machine:

git clone https://github.com/pinterest/ktlint && cd ktlint\n./gradlew tasks # shows how to build, test, run, etc. project\n

Tip

To open and run ktlint in Intellij IDEA:

"},{"location":"install/cli/","title":"Command line","text":"

Command Line usage

If you don't plan to use ktlint's command line interface then you can skip this section.

"},{"location":"install/cli/#download-and-verification","title":"Download and verification","text":""},{"location":"install/cli/#download-manually-from-github","title":"Download manually from github","text":"

All releases of ktlint can be downloaded from the releases page.

"},{"location":"install/cli/#download-using-curl","title":"Download using curl","text":"

A particular version of ktlint can be downloaded with next command which also changes the file to an executable in directory /usr/local/bin:

Download
curl -sSLO https://github.com/pinterest/ktlint/releases/download/1.4.0/ktlint && chmod a+x ktlint && sudo mv ktlint /usr/local/bin/\n

Curl not installed or behind proxy

If you don't have curl installed - replace curl -sL with wget -qO-. If you are behind a proxy see - curl / wget manpage. Usually simple:

http_proxy=http://proxy-server:port https_proxy=http://proxy-server:port curl -sL ...\n

"},{"location":"install/cli/#verification-of-download","title":"Verification of download","text":"

ktlint.asc contains PGP signature which you can verify with:

Verify releases 0.32.0 and above
curl -sS https://keybase.io/ktlint/pgp_keys.asc | gpg --import && gpg --verify ktlint.asc\n
Verify releases up through 0.31.0
curl -sS https://keybase.io/shyiko/pgp_keys.asc | gpg --import && gpg --verify ktlint.asc\n
"},{"location":"install/cli/#package-managers","title":"Package managers","text":"

ktlint can be installed via several OS specific package managers.

Install with brew on macOS or Homebrew on Linux

brew install ktlint\n

Install with MacPorts

port install ktlint\n

"},{"location":"install/cli/#command-line-usage","title":"Command line usage","text":""},{"location":"install/cli/#rule-sets","title":"Rule set(s)","text":"

When no arguments are specified, the style of all Kotlin files (ending with '.kt' or '.kts') inside the current dir (recursively) are validated with the rules from the standard ruleset. Hidden folders will be skipped.

Default validation with standard ruleset
ktlint\n

Note

The experimental rules in the standard rule set will only be run when .editorconfig property ktlint_experimental = enabled is set.

To validate with a custom ruleset run command below:

Validation with standard and a custom ruleset
ktlint --ruleset=/path/to/custom-ruleset.jar\n# or\nktlint -R /path/to/custom-ruleset.jar\n

Note

If the custom rule set contains rules that are marked as experimental, those rule will only be run when .editorconfig property ktlint_experimental = enabled is set.

"},{"location":"install/cli/#format-autocorrect","title":"Format (autocorrect)","text":"

Most style violations can be corrected automatically. Errors that can not be corrected, are printed to stderr.

Autocorrect style violations
ktlint --format\n# or\nktlint -F\n
"},{"location":"install/cli/#globs","title":"Globs","text":"

Globs can be used to specify more exactly what files and directories are to be validated. ktlint uses the .gitignore pattern style syntax for globs. Globs are processed from left to right. Prepend a glob with ! to negate it. Hidden folders will be skipped.

Check only certain locations starting from the current directory
# Check all '.kt' files in 'src/' directory, but ignore files ending with 'Test.kt':\nktlint 'src/**/*.kt' '!src/**/*Test.kt'\n\n# Check all '.kt' files in 'src/' directory, but ignore 'generated' directory and its subdirectories:\nktlint 'src/**/*.kt' '!src/**/generated/**'\n
"},{"location":"install/cli/#violation-reporting","title":"Violation reporting","text":"

ktlint supports different type of reporters for lint violations. When not specified the plain reporter is used. Optionally the plain reporter can group the violations per file.

Style violation grouped by file
$ ktlint --reporter=plain?group_by_file\n

When using ktlint on an existing project, the number of violations can be huge. To get more insights in which rules are causing the most violations, the plain-summary reporter can be used. Style violations counted per rule

$ ktlint --reporter=plain-summary\n

Other built-in reporters are: json, sarif, checkstyle, and html

Style violations can be written to an output file which is convenient when multiple reporters are specified. In example below, the plain reporter is used to write to the console while the checkstyle reports is written to a file:

Multiple reporters
ktlint --reporter=plain --reporter=checkstyle,output=ktlint-report-in-checkstyle-format.xml\n

If resolving all existing errors in a project is unwanted, it is possible to create a baseline and in following invocations compare violations against this baseline. Violations that are registered in the baseline, will be ignored silently. Remove the baseline file in case you want to reset it.

Check against a baseline file
ktlint --baseline=ktlint-baseline.xml # Baseline is created when not existing\n
"},{"location":"install/cli/#logging","title":"Logging","text":"

Logging information is written to stdout. The amount of logging can be influenced by setting the minimal log level using option --log-level or -l to one of values trace, debug, info, warn, error, or none to suppress all logging.

By default, the info log level is used meaning that all log lines at level info, warn and error are shown while suppressing log lines at level debug or trace.

"},{"location":"install/cli/#rule-configuration-editorconfig","title":"Rule configuration (.editorconfig)","text":"

Some rules can be tweaked via the editorconfig file.

A scaffold of the .editorconfig file can be generated with command below. Note: that the generated file only contains configuration settings which are actively used by the rules which are loaded:

Generate .editorconfig
# Specify the code style(ktlint_official, intellij_idea or android_studio) to be used when generating the .editorconfig\nktlint generateEditorConfig ktlint_official\n# or\nktlint --ruleset=/path/to/custom-ruleset.jar generateEditorConfig android_studio\n

Normally the .editorconfig file is located in the root of your project directory. In case the file is located in a sub folder of the project, the settings of that file only applies to that subdirectory and its folders (recursively). Ktlint automatically detects and reads all .editorconfig files in your project.

Use command below, to specify a default editorconfig. In case a property is not defined in any .editorconfig file on the path to the file, the value from the default file is used. The path may point to any valid file or directory. The path can be relative or absolute. Depending on your OS, the \"~\" at the beginning of a path is replaced by the user home directory.

Override '.editorconfig'
ktlint --editorconfig=/path/to/.editorconfig\n

Overrides '.editorconfig' in project directory\" in KtLint 0.46 and older

When specifying this option using ktlint 0.46 or older, all .editorconfig files in the project directory are being ignored. Starting from KtLint 0.47 the properties in this file are used as fallback.

"},{"location":"install/cli/#stdin-stdout","title":"Stdin && stdout","text":"

With command below, the input is read from stdin and the violations are printed to stderr. Logging is written to stdout.

Lint from stdin
ktlint --stdin\n

When combined with the --format option, the formatted code is written to stdout and the violations are printed to stderr:

Format from stdin and write to stdout
ktlint --stdin -F\n

Suppress logging and error output

Logging output printed to stdout can be suppressed by setting --log-level=none (see logging). Output printed to stderr can be suppressed in different ways. To ignore all error output, add 2> /dev/null to the end of the command line. Otherwise, specify a reporter to write the error output to a file.

If input from stdin represents the contents of a file, the file path can be supplied with stdin-path. This path is made available for rules to use, the --format option will not modify this file.

file path from stdin-path
ktlint --stdin --stdin-path /path/to/file/Foo.kt\n
"},{"location":"install/cli/#git-hooks","title":"Git hooks","text":"

Predefined git hooks can be installed, to automatically validate lint errors before commit or push.

Install git pre-commit hook
ktlint installGitPreCommitHook\n
Install git pre-push hook
ktlint installGitPrePushHook\n
"},{"location":"install/cli/#miscellaneous-flags-and-commands","title":"Miscellaneous flags and commands","text":"

--color and --color-name=<colorName>: Make output colorful and optionally set the color name to use.

-h or --help: Prints help information.

--limit=<limit>: Maximum number of errors to show (default: show all)

--relative: Print files relative to the working directory (e.g. dir/file.kt instead of /home/user/project/dir/file.kt)

--patterns-from-stdin[=<delimiter>]: Reads additional patterns from stdin, where the patterns are separated by <delimiter>. If =<delimiter> is omitted, newline is used as fallback delimiter. If an empty string is given, the NUL byte is used as delimiter instead. If this option is given, then the default patterns are disabled. Options --stdin and --patterns-from-stdin are mutually exclusive, only one of them can be given at a time.

-V or --version: Prints version information and exit.

"},{"location":"install/cli/#microsoft-windows-users","title":"Microsoft Windows users","text":"

Microsoft Windows is not able to run the ktlint command directly. Ktlint can be run in following ways on Microsoft Windows:

  1. Use the ktlint.bat batch file provided as part of the release. Add the batch file to your %PATH% environment variable for easy access
  2. Run ktlint using Git Bash
  3. Run as java -jar ktlint
"},{"location":"install/integrations/","title":"Integrations","text":""},{"location":"install/integrations/#maven-integration","title":"Maven integration","text":"

By adding the plugin definition below to the <plugins> section in the pom.xml:

See cli usage for arguments that can be supplied to ktlint.

Adding plugin to pom.xml
...\n<plugin>\n    <groupId>org.apache.maven.plugins</groupId>\n    <artifactId>maven-antrun-plugin</artifactId>\n    <version>3.1.0</version>\n    <executions>\n        <execution>\n            <id>ktlint</id>\n            <phase>verify</phase>\n            <configuration>\n            <target name=\"ktlint\">\n                <java taskname=\"ktlint\" dir=\"${basedir}\" fork=\"true\" failonerror=\"true\"\n                    classpathref=\"maven.plugin.classpath\" classname=\"com.pinterest.ktlint.Main\">\n                  <!-- Note: the JVM arg below is only required when running ktlint with Java 16+ in format mode.\n                  <jvmarg value=\"--add-opens=java.base/java.lang=ALL-UNNAMED\"/>\n                  -->\n                  <!-- see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information -->\n                  <arg value=\"src/**/*.kt\"/>\n                </java>\n            </target>\n            </configuration>\n            <goals>\n                <goal>run</goal>\n            </goals>\n        </execution>\n        <execution>\n            <id>ktlint-format</id>\n            <configuration>\n            <target name=\"ktlint\">\n                <java taskname=\"ktlint\" dir=\"${basedir}\" fork=\"true\" failonerror=\"true\"\n                    classpathref=\"maven.plugin.classpath\" classname=\"com.pinterest.ktlint.Main\">\n                    <!-- Note: the JVM args below is only required when running ktlint with Java 16+ in format mode -->\n                    <jvmarg value=\"--add-opens=java.base/java.lang=ALL-UNNAMED\"/>\n                    <!-- see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information -->\n                    <arg value=\"-F\"/>\n                    <arg value=\"src/**/*.kt\"/>\n                </java>\n            </target>\n            </configuration>\n            <goals>\n                <goal>run</goal>\n            </goals>\n        </execution>\n    </executions>\n    <dependencies>\n        <dependency>\n            <groupId>com.pinterest.ktlint</groupId>\n            <artifactId>ktlint-cli</artifactId>\n            <version>1.4.0</version>\n        </dependency>\n        <!-- additional 3rd party ruleset(s) can be specified here -->\n    </dependencies>\n</plugin>\n...\n

Tip

If you want ktlint to run before code compilation takes place - change <phase>verify</phase> to <phase>validate</phase> (see Maven Build Lifecycle for more).

ktlint-maven-plugin

You might be interested to use the dedicated gantsign/ktlint-maven-plugin.

"},{"location":"install/integrations/#gradle-integration","title":"Gradle integration","text":""},{"location":"install/integrations/#jlleitschuhktlint-gradle","title":"jlleitschuh/ktlint-gradle","text":"

The jlleitschuh/ktlint-gradle Gradle plugin automatically creates check and format tasks for project Kotlin sources. It supports different kotlin plugins and Gradle build caching.

"},{"location":"install/integrations/#jeremymailenkotlinter-gradle","title":"jeremymailen/kotlinter-gradle","text":"

The jeremymailen/kotlinter-gradle Gradle plugin features incremental build support, file reports, and *.kts source support.

"},{"location":"install/integrations/#diffplugspotless","title":"diffplug/spotless","text":"

The diffplug/spotless Gradle plugin is a general-purpose formatting plugin which amongst many others also supports ktlint.

"},{"location":"install/integrations/#autostyleautostyle","title":"autostyle/autostyle","text":"

The autostyle/autostyle Gradle plugin is a general-purpose formatting plugin which amongst others also supports ktlint.

"},{"location":"install/integrations/#custom-gradle-integration","title":"Custom Gradle integration","text":""},{"location":"install/integrations/#custom-gradle-integration-with-groovy","title":"Custom Gradle integration with Groovy","text":"

Warning

It is recommended to use one of the Gradle plugins mentioned before.

The configuration below, defines following task:

build.gradle
// kotlin-gradle-plugin must be applied for configuration below to work\n// (see https://kotlinlang.org/docs/reference/using-gradle.html)\n\nplugins {\n    id 'java'\n}\n\nrepositories {\n    mavenCentral()\n}\n\nconfigurations {\n    ktlint\n}\n\ndependencies {\n    ktlint(\"com.pinterest.ktlint:ktlint-cli:1.4.0\") {\n        attributes {\n            attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))\n        }\n    }\n    // additional 3rd party ruleset(s) can be specified here\n    // just add them to the classpath (e.g. ktlint 'groupId:artifactId:version') and \n    // ktlint will pick them up\n}\n\ntasks.register(\"ktlintCheck\", JavaExec) {\n    group = \"verification\"\n    description = \"Check Kotlin code style.\"\n    classpath = configurations.ktlint\n    mainClass = \"com.pinterest.ktlint.Main\"\n    // see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information\n    args \"src/**/*.kt\", \"**.kts\", \"!**/build/**\"\n}\n\ntasks.named(\"check\") {\n    dependsOn tasks.named(\"ktlintCheck\")\n}\n\ntasks.register(\"ktlintFormat\", JavaExec) {\n    group = \"formatting\"\n    description = \"Fix Kotlin code style deviations.\"\n    classpath = configurations.ktlint\n    mainClass = \"com.pinterest.ktlint.Main\"\n    jvmArgs \"--add-opens=java.base/java.lang=ALL-UNNAMED\"\n    // see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information\n    args \"-F\", \"src/**/*.kt\", \"**.kts\", \"!**/build/**\"\n}\n

See Making your Gradle tasks incremental by Niklas Baudy on how to make tasks above incremental.

"},{"location":"install/integrations/#custom-gradle-integration-with-kotlin-dsl","title":"Custom Gradle integration with Kotlin DSL","text":"

Warning

It is recommended to use one of the Gradle plugins mentioned before.

The configuration below, defines following task:

build.gradle.kts
val ktlint by configurations.creating\n\ndependencies {\n    ktlint(\"com.pinterest.ktlint:ktlint-cli:1.4.0\") {\n        attributes {\n            attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))\n        }\n    }\n    // ktlint(project(\":custom-ktlint-ruleset\")) // in case of custom ruleset\n}\n\nval ktlintCheck by tasks.registering(JavaExec::class) {\n    group = LifecycleBasePlugin.VERIFICATION_GROUP\n    description = \"Check Kotlin code style\"\n    classpath = ktlint\n    mainClass.set(\"com.pinterest.ktlint.Main\")\n    // see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information\n    args(\n        \"**/src/**/*.kt\",\n        \"**.kts\",\n        \"!**/build/**\",\n    )\n}\n\ntasks.check {\n    dependsOn(ktlintCheck)\n}\n\ntasks.register<JavaExec>(\"ktlintFormat\") {\n    group = LifecycleBasePlugin.VERIFICATION_GROUP\n    description = \"Check Kotlin code style and format\"\n    classpath = ktlint\n    mainClass.set(\"com.pinterest.ktlint.Main\")\n    jvmArgs(\"--add-opens=java.base/java.lang=ALL-UNNAMED\")\n    // see https://pinterest.github.io/ktlint/install/cli/#command-line-usage for more information\n    args(\n        \"-F\",\n        \"**/src/**/*.kt\",\n        \"**.kts\",\n        \"!**/build/**\",\n    )\n}\n
"},{"location":"install/integrations/#gnu-emacs-integration","title":"GNU Emacs integration","text":"

See whirm/flycheck-kotlin.

"},{"location":"install/integrations/#vim-integration","title":"Vim integration","text":"

See w0rp/ale.

"},{"location":"install/integrations/#mega-linter-integration","title":"Mega-Linter integration","text":"

The Mega-Linter integrates 70+ linters in a single tool for CI, including ktlint activated out of the box

"},{"location":"install/integrations/#tca-integration","title":"TCA integration","text":"

Tencent Cloud Code Analysis (TCA for short, code-named CodeDog inside the company early) is a comprehensive platform for code analysis and issue tracking. TCA consist of three components, server, web and client. It integrates of a number of self-developed tools, and also supports dynamic integration of code analysis tools in various programming languages.

"},{"location":"install/integrations/#other-integration","title":"Other integration","text":"

Do you know any other integration with ktlint then please create a PR to add this integration to our documentation.

"},{"location":"install/setup/","title":"Recommended setup","text":"

Ktlint can be installed in a lot of different ways. It depends on your situation what works best for you.

As maintainer of Ktlint, I advise setup below to maximize your productivity, and get feedback early according to the failing fast principle.

  1. ktlint-intellij-plugin for direct feedback while coding
  2. Git pre-commit hook for feedback when committing
  3. Build pipeline as last defence
"},{"location":"install/setup/#ktlint-intellij-plugin-for-direct-feedback-while-coding","title":"ktlint-intellij-plugin for direct feedback while coding","text":"

Tip

Ensure to install version 0.20.0 (or later) of the Ktlint plugin via the Intellij Plugin Marketplace to get benefits described below.

The ktlint-intellij-plugin gives direct feedback while writing code. The plugin can be used in 'distract free' and 'manual' mode, or be disabled entirely. This is a per-project setting.

In distract free mode, the plugin only shows the violations which need to be manually corrected. Ktlint formatting will be applied automatically after apply Intellij IDEA format, or on save of the file. This works bests for projects for which the .editorconfig already has been set up properly for the project.

Note that image above also shows a warning that 'Ktlint found 5 violations which can be autocorrected'. Reformatting the file, or simply save the file, results in:

In 'manual' mode, or in 'distract free' mode after selecting 'Show all Ktlint violations in file', each individual violation is shown as error. This allows for suppressing errors that can be autocorrected, but for which this is unwanted.

Violations reported by ktlint can be suppressed by adding a @Suppress annotation via the quick fix:

As of Ktlint 1.1.0 the maintainer of Ktlint has joined the ktlint-intellij-plugin project to ensure that the plugin stays up to date with releases of ktlint and releases of Intellij IDEA.

The ktlint-intellij-plugin can be installed as plugin in Intellij IDEA.

"},{"location":"install/setup/#git-pre-commit-hook-for-feedback-when-committing","title":"Git pre-commit hook for feedback when committing","text":"

The git pre-commit hook, protects against committing code containing lint violations. From the perspective of code reviewing it is important that the code is already formatted in the style of the project. This is especially valuable after refactorings (for example search and replace) have been applied on files that are not opened in the editor and as of that might not have been updated by the ktlint-intellij-plugin.

Ktlint CLI can generate a pre-commit hook, or you can find it here.

"},{"location":"install/setup/#build-pipeline-as-last-defence","title":"Build pipeline as last defence","text":"

As last defence, to ensure that the code base does not contain lint violations, ktlint-cli is run in the (local and remote) build pipeline (see integrations.

For example, in my maven projects I have bound the ktlint (linting) task to the maven compile lifecycle. If after compile a lint violation is found the build is failed. This circumvents that developers disable running of the git hooks on their local machine. And in case that the code was not build locally, the remote build pipeline fails as last resort.

"},{"location":"install/snapshot-build/","title":"Snapshot build","text":""},{"location":"install/snapshot-build/#access-to-the-latest-master-snapshot","title":"Access to the latest master snapshot","text":"

Whenever a commit is added to the master branch a snapshot build is automatically uploaded to Sonatype's snapshots repository. If you are eager to try upcoming changes (that might or might not be included in the next stable release) you can do so by changing version of ktlint to <latest-version>-SNAPSHOT + adding a repo:

"},{"location":"install/snapshot-build/#maven","title":"Maven","text":"
...\n<repository>\n    <id>sonatype-snapshots</id>\n    <url>https://oss.sonatype.org/content/repositories/snapshots</url>\n    <snapshots>\n        <enabled>true</enabled>\n    </snapshots>\n    <releases>\n        <enabled>false</enabled>\n    </releases>\n</repository>\n...\n
"},{"location":"install/snapshot-build/#gradle","title":"Gradle","text":"
repositories {\n  maven {\n    url \"https://oss.sonatype.org/content/repositories/snapshots\"\n  }\n}\n
"},{"location":"install/snapshot-build/#kotlin-development-version-snapshot","title":"Kotlin development version snapshot","text":"

Additionally, project publishes snapshots build against latest kotlin development version. To use them, change version of ktlint to <latest-version>-kotlin-dev-SNAPSHOT.

"},{"location":"rules/","title":"Index","text":"

= Rules

"},{"location":"rules/code-styles/","title":"Code styles","text":"

Starting from version 1.0, ktlint_official is the default code style. If you want to revert to another code style, then set the .editorconfig property ktlint_code_style.

[*.{kt,kts}]\nktlint_code_style = intellij_idea # or android_studio or ktlint_official (default)\n

The ktlint_official code style combines the best elements from the Kotlin Coding conventions and Android's Kotlin styleguide. This code style also provides additional formatting on topics which are not (explicitly) mentioned in those conventions and style guide.

Note

Be aware that this code style in some cases formats code in a way which is not accepted by the default code formatters in IntelliJ IDEA and Android Studio. The formatters of those editors produce nicely formatted code in the vast majority of cases. But in a number of edge cases, the formatting contains bugs which are waiting to be fixed for several years. The new code style formats code in a way which is compatible with the default formatting of the editors whenever possible. When using this codestyle, it is best to disable (e.g. not use) code formatting in the editor.

"},{"location":"rules/configuration-intellij-idea/","title":"Intellij IDEA configuration","text":"

ktlint strives to prevent code formatting conflicts with IntelliJ IDEA / Android Studio as much as possible. In some cases, ktlint deliberately deviates from IDEA formatting.

"},{"location":"rules/configuration-intellij-idea/#preventing-conflicts","title":"Preventing conflicts","text":"

Many conflicts can be prevented by setting following .editorconfig settings:

root = true\n\n[*]\ninsert_final_newline = true\n\n[{*.kt,*.kts}]\nij_kotlin_code_style_defaults = KOTLIN_OFFICIAL\n\n#  Disable wildcard imports entirely\nij_kotlin_name_count_to_use_star_import = 2147483647\nij_kotlin_name_count_to_use_star_import_for_members = 2147483647\nij_kotlin_packages_to_use_import_on_demand = unset\n

Conflicts between ktlint and IDEA formatting can also be resolved by using the ktlint-intellij-plugin (or install via Intellij IDEA plugin marketplace) in distract free mode. In this mode, the plugin formats your code with ktlint while you're editing the code.

"},{"location":"rules/configuration-intellij-idea/#cleaning-up-old-xml-configuration-settings","title":"Cleaning up old XML configuration settings","text":"

Projects which have been created with (old)er versions of Intellij IDEA might still contain XML configuration regarding code styling. It is advised to remove the directory .idea/codeStyles whenever it still exists in your project directory.

"},{"location":"rules/configuration-ktlint/","title":"KtLint configuration","text":"

Ktlint uses a limited set of .editorconfig properties for additional configuration. A sensible default value is provided for each property when not explicitly defined. Properties can be overridden, provided they are specified under [*.{kt,kts}]. Ktlint uses some properties defined by .editorconfig, IntelliJ IDEA and custom properties.

Danger

Unfortunately IntelliJ IDEA has an autoformat issue regarding .editorconfig. Due to this error an additional space is added between glob statements, resulting in [*{kt, kts}] instead of [*{kt,kts}]. The .editorconfig library used by ktlint ignores sections after encountering a space in the list. As a result, the rule is not applied on all files as documented in the original ktlint issue.

"},{"location":"rules/configuration-ktlint/#code-style","title":"Code style","text":"

By default, the ktlint_official code style is applied. Alternatively, the code style can be set to intellij_idea or android_studio.

[*.{kt,kts}]\nktlint_code_style = ktlint_official\n
"},{"location":"rules/configuration-ktlint/#disable-rules","title":"Disable rule(s)","text":"

Rule sets and individual rules can be disabled / enabled with a separate property per rule (set).

All rules in a rule set can be enabled or disabled with a rule set property. The name of the rule set property consists of the ktlint_ prefix followed by the rule set id. Examples:

ktlint_standard = disabled # Disable all rules from the `standard` rule set provided by KtLint\nktlint_experimental = enabled # Enable all `experimental` rules from all rule sets provided by KtLint or other rule providers\nktlint_custom-rule-set = enabled # Enable all rules in the `custom-rule-set` rule set (not provided by KtLint)\n

Rules that are marked as experimental will not be run, unless explicitly enabled:

ktlint_experimental = enabled # Enable rules marked as experimental for all rule sets that are enabled\n

An individual rule can be enabled or disabled with a rule property. The name of the rule property consists of the ktlint_ prefix followed by the rule set id followed by a _ and the rule id. Examples:

ktlint_standard_final-newline = disabled # Disables the `final-newline` rule provided by KtLint\nktlint_standard_some-experimental-rule = enabled # Enables the (experimental) `some-experimental-rule` in the `standard` rule set provided by KtLint\nktlint_custom-rule-set_custom-rule = disabled # Disables the `custom-rule` rule in the `custom-rule-set` rule set (not provided by KtLint)\n

Note

The rule properties are applied after applying the rule set properties and take precedence. So if a rule set is disabled but a specific rule of that rule set is enabled, then the rule will be executed.

"},{"location":"rules/configuration-ktlint/#rule-specific-configuration-settings","title":"Rule specific configuration settings","text":"

The configuration settings below are used to configure the behavior of a specific rule. As of that, those settings only take effect when the corresponding rule is enabled. See description of rule for more information about the setting.

Configuration setting Rule ij_kotlin_allow_trailing_comma trailing-comma-on-declaration-site ij_kotlin_allow_trailing_comma_on_call_site trailing-comma-on-call-site ij_kotlin_packages_to_use_import_on_demand no-wildcard-imports indent_size indent indent_style indent insert_final_newline final-newline ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_than chain-method-continuation ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than class-signature ktlint_ignore_back_ticked_identifier max-line-length ktlint_function_naming_ignore_when_annotated_with function-naming ktlint_function_signature_body_expression_wrapping function-signature ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than function-signature max_line_length max-line-length and several other rules"},{"location":"rules/configuration-ktlint/#overriding-editorconfig-properties-for-specific-directories","title":"Overriding Editorconfig properties for specific directories","text":"

You can override properties for specific directories inside your project:

[*.{kt,kts}]\nktlint_standard_import-ordering = disabled\n\n[api/*.{kt,kts}]\nktlint_standard_indent = disabled\n

Note that in example above the import-ordering rule is disabled for all packages including the api sub package. Next to this the indent rule is disabled for the api package and its sub packages.

"},{"location":"rules/dependencies/","title":"Dependencies","text":"

Preferably rules run independent of each other. In some case this is however not feasible. The diagram below shows the dependencies between the rules provided by KtLint.

"},{"location":"rules/experimental/","title":"Experimental rules","text":"

Important

Up and until Ktlint version 0.47, experimental were located in a separate experimental rule set. As of Ktlint version 0.48, each rule set can optionally define experimental rules.

All experimental rules described below are part of the standard rule set of Ktlint. To enable all experimental rules (from all rule sets), set editorconfig property below:

[*.{kt,kts}]\nktlint_experimental=enabled\n
Also see enable/disable specific rules.

"},{"location":"rules/experimental/#blank-line-between-when-conditions","title":"Blank line between when-conditions","text":"

Consistently add or remove blank line between when-conditions in a when-statement. A blank line is only added between when-conditions if the when-statement contains at lease one multiline when-condition. If a when-statement only contains single line when-conditions, then the blank lines between the when-conditions are removed.

Note

Ktlint uses .editorconfig property ij_kotlin_line_break_after_multiline_when_entry but applies it also on single line entries to increase consistency.

Ktlint Disallowed
val foo1 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> \"bar2\"\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = true\nval foo2 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n\n        BAR2 -> {\n            \"bar2\"\n        }\n\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = true\nval foo3 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n\n        // BAR2 comment\n        BAR2 -> \"bar2\"\n\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = false\nval foo4 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> {\n            \"bar2\"\n        }\n        else -> null\n    }\n
// ij_kotlin_line_break_after_multiline_when_entry = true | false (no blank lines in simple when-statement)\nval foo1 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n\n        BAR2 -> \"bar2\"\n\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = true (missing newline after BAR1)\nval foo2 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> {\n            \"bar2\"\n        }\n\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = true (missing newline after BAR1, and BAR2)\nval foo3 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        // BAR2 comment\n        BAR2 -> \"bar2\"\n        else -> null\n    }\n\n// ij_kotlin_line_break_after_multiline_when_entry = false (unexpected newline after BAR2)\nval foo4 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> {\n            \"bar2\"\n        }\n\n        else -> null\n    }\n
Configuration setting ktlint_official intellij_idea android_studio ij_kotlin_line_break_after_multiline_when_entryDespite its name, forces a blank line between single line and multiline when-entries when at least one multiline when-entry is found in the when-statement. true true true

Rule id: standard:blank-line-between-when-conditions

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:blank-line-between-when-conditions\")\n
    Enable rule via .editorconfig
    ktlint_standard_blank-line-between-when-conditions = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_blank-line-between-when-conditions = disabled\n
"},{"location":"rules/experimental/#kdoc","title":"KDoc","text":"

KDoc's should only be used on elements for which KDoc is to be transformed to documentation. Normal block comments should be used in other cases.

!!! note: Access modifiers are ignored. Strictly speaking, one could argue that private declarations should not have a KDoc as no documentation will be generated for it. However, for internal use of developers the KDoc still serves documentation purposes.

Ktlint Disallowed
/** some KDoc */\nclass FooBar(\n    /** some KDoc */\n    val foo: Foo\n) {\n    /**\n     * Some bar KDoc\n     */\n    constructor() : this()\n\n    /** some KDoc */\n    val bar: Bar\n}\n\nenum class Foo {\n    /** some KDoc */\n    BAR\n}\n\n/** some KDoc */\ninterface Foo\n/** some KDoc */\nfun foo()\n/** some KDoc */\nval foo: Foo\n/** some KDoc */\nobject foo: Foo\n/** some KDoc */\ntypealias FooBar = (Foo) -> Bar\n
/**\n * Some dangling Kdoc (e.g. not followed by a declaration)\n */\n\nval foo /** Some KDoc */ = \"foo\"\n\nclass Foo(\n    /** some dangling KDoc inside a parameter list */\n)\n

Rule id: standard:kdoc

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:kdoc\")\n
    Enable rule via .editorconfig
    ktlint_standard_kdoc = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_kdoc = disabled\n
"},{"location":"rules/experimental/#mixed-condition-operators","title":"Mixed condition operators","text":"

Conditions should not use a both && and || operators between operators at the same level. By using parenthesis the expression is to be clarified.

Ktlint Disallowed
val foo = bar1 && (bar2 || bar3) && bar4\n
val foo = bar1 &&\n    bar2 ||\n    bar3\nval foo = bar1 && (bar2 || bar3 && bar4) && bar5\n

Rule id: standard:mixed-condition-operators

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:mixed-condition-operators\")\n
    Enable rule via .editorconfig
    ktlint_standard_mixed-condition-operators = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_mixed-condition-operators = disabled\n
"},{"location":"rules/experimental/#square-brackets-spacing","title":"Square brackets spacing","text":"

Check for spacing around square brackets.

Ktlint Disallowed
val foo1 = bar[1]\nval foo2 =\n   bar[\n       1,\n       2,\n   ]\n\n@Foo(\n    fooBar = [\"foo\", \"bar\"],\n    fooBaz = [\n        \"foo\",\n        \"baz\",\n    ],\n)\nfun foo() {}\n
val foo1 = bar [1]\nval foo2 = bar[ 1]\nval foo3 = bar[1 ]\n

Rule id: standard:square-brackets-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:square-brackets-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_square-brackets-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_square-brackets-spacing = disabled\n
"},{"location":"rules/experimental/#when-entry-bracing","title":"When-entry bracing","text":"

Enforce consistent usages of braces inside the when-statement. All when-entries in the when-statement should use braces around their bodies in case at least one when-entry has a multiline body, or when the body is surrounded by braces.

Braces are helpful for following reasons:

This rule is not incorporated in the Kotlin Coding conventions, nor in the Android Kotlin Styleguide. It is based on similar behavior in enforcing consistent use of braces in if-else statements. As of that the rule is only enabled automatically for code style ktlint_official. It can be enabled explicitly for other code styles.

Ktlint Disallowed
val foo1 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> \"bar2\"\n        else -> null\n    }\n\nval foo2 =\n    when (bar) {\n        BAR1 -> {\n            \"bar1\"\n        }\n        BAR2 -> {\n            \"bar2\"\n        }\n        else -> {\n            null\n        }\n    }\n
val foo3 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 -> {\n            \"bar2\"\n        }\n        else -> null\n    }\n\nval foo4 =\n    when (bar) {\n        BAR1 -> \"bar1\"\n        BAR2 ->\n            \"bar2\"\n        else -> null\n    }\n

Rule id: standard:when-entry-bracing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:when-entry-bracing\")\n
    Enable rule via .editorconfig
    ktlint_standard_when-entry-bracing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_when-entry-bracing = disabled\n
"},{"location":"rules/standard/","title":"Standard rules","text":""},{"location":"rules/standard/#annotation-formatting","title":"Annotation formatting","text":"

Multiple annotations should be on a separate line than the annotated declaration; annotations with parameters should each be on separate lines; annotations should be followed by a space

Ktlint Disallowed
// A single annotation (without parameters) is allowed on same line as annotated construct\n@FunctionalInterface class FooBar {\n    @JvmField var foo: String\n\n    @Test fun bar() {}\n}\n\n// A class or function parameter may have a single annotation with parameter(s) on the same line\nclass Foo(\n    @Path(\"fooId\") val fooId: String,\n    @NotNull(\"bar\") bar: String,\n)\n\n// Multiple annotations (without parameters) are allowed on the same line\n@Foo @Bar\nclass FooBar {\n    @Foo @Bar\n    var foo: String\n\n    @Foo @Bar\n    fun bar() {}\n}\n\n// An array of annotations (without parameters) is allowed on same line as annotated construct\n@[Foo Bar] class FooBar2 {\n    @[Foo Bar] var foo: String\n\n    @[Foo Bar] fun bar() {}\n}\n
// An annotation with parameter(s) is not allowed on same line as annotated construct\n@Suppress(\"Unused\") class FooBar {\n    @Suppress(\"Unused\") var foo: String\n    @Suppress(\"Unused\") fun bar() {}\n}\n// Multiple annotation on same line as annotated construct are not allowed\n@Foo @Bar class FooBar {\n    @Foo @Bar var foo: String\n    @Foo @Bar fun bar() {}\n}\n

Rule id: standard:annotation

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:annotation\")\n
    Enable rule via .editorconfig
    ktlint_standard_annotation = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_annotation = disabled\n
"},{"location":"rules/standard/#binary-expression-wrapping","title":"Binary expression wrapping","text":"

Wraps binary expression at the operator reference whenever the binary expression does not fit on the line. In case the binary expression is nested, the expression is evaluated from outside to inside. If the left and right hand sides of the binary expression, after wrapping, fit on a single line then the inner binary expressions will not be wrapped. If one or both inner binary expression still do not fit on a single after wrapping of the outer binary expression, then each of those inner binary expressions will be wrapped.

Ktlint Disallowed
fun foo() {\n    // Assume that the last allowed character is\n    // at the X character on the right                       X\n    if ((leftHandSideExpression && rightHandSideExpression) ||\n        (\n            leftHandSideLongExpression &&\n                rightHandSideExpression\n        )\n    ) {\n        // do something\n    }\n}\n
fun foo() {\n    // Assume that the last allowed character is\n    // at the X character on the right                       X\n    if ((leftHandSideExpression && rightHandSideExpression) ||\n        (leftHandSideLongExpression && rightHandSideExpression)\n    ) {\n        // do something\n    }\n}\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:binary-expression-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:binary-expression-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_binary-expression-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_binary-expression-wrapping = disabled\n
"},{"location":"rules/standard/#blank-line-before-declarations","title":"Blank line before declarations","text":"

Requires a blank line before any class or function declaration. No blank line is required between the class signature and the first declaration in the class. In a similar way, a blank line is required before any list of top level or class properties. No blank line is required before local properties or between consecutive properties.

Ktlint Disallowed
const val FOO_1 = \"foo1\"\n\nclass FooBar {\n    val foo2 = \"foo2\"\n    val foo3 = \"foo3\"\n\n    fun bar1() {\n        val foo4 = \"foo4\"\n        val foo5 = \"foo5\"\n    }\n\n    fun bar2() = \"bar\"\n\n    val foo6 = \"foo3\"\n    val foo7 = \"foo4\"\n\n    enum class Foo\n}\n
const val FOO_1 = \"foo1\"\n\nclass FooBar {\n    val foo2 = \"foo2\"\n    val foo3 = \"foo3\"\n    fun bar1() {\n        val foo4 = \"foo4\"\n        val foo5 = \"foo5\"\n    }\n    fun bar2() = \"bar\"\n    val foo6 = \"foo3\"\n    val foo7 = \"foo4\"\n    enum class Foo\n}\n

Rule id: standard:blank-line-before-declaration

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:blank-line-before-declaration\")\n
    Enable rule via .editorconfig
    ktlint_standard_blank-line-before-declaration = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_blank-line-before-declaration = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#block-comment-initial-star-alignment","title":"Block comment initial star alignment","text":"

Lines in a block comment which (exclusive the indentation) start with a * should have this * aligned with the * in the opening of the block comment.

Ktlint Disallowed
/*\n * This comment is formatted well.\n */\n
/*\n      * This comment is not formatted well.\n    */\n

Rule id: standard:block-comment-initial-star-alignment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:block-comment-initial-star-alignment\")\n
    Enable rule via .editorconfig
    ktlint_standard_block-comment-initial-star-alignment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_block-comment-initial-star-alignment = disabled\n
"},{"location":"rules/standard/#chain-method-continuation","title":"Chain method continuation","text":"

In a multiline method chain, the chain operators (. or ?.) have to be aligned with each other.

Multiple chained methods on a single line are allowed as long as the maximum line length, and the maximum number of chain operators are not exceeded. Under certain conditions, it is allowed that the expression before the first and/or the expression after the last chain operator is a multiline expression.

The . in java.class is ignored when wrapping on chain operators.

Warning

A binary expression for which the left and/or right operand consist of a method chain are currently being ignored by this rule. Please reach out, if you can help to determine what the best strategy is to deal with such kind of expressions.

Ktlint Disallowed
val foo1 =\n    listOf(1, 2, 3)\n        .filter { it > 2 }!!\n        .takeIf { it > 2 }\n        .map {\n            it * it\n        }?.map {\n            it * it\n        }\nval foo2 =\n    listOf(1, 2, 3)\n        .filter {\n            it > 2\n        }.map {\n            2 * it\n        }?.map {\n            2 * it\n        }\nval foo3 =\n    foo().bar().map {\n        it.foobar()\n    }\nval foo4 =\n    \"\"\"\n    Some text\n    \"\"\".trimIndent().foo().bar()\n
val foo1 =\n    listOf(1, 2, 3).\n        filter { it > 2 }!!.\n        takeIf { it > 2 }.\n        map {\n            it * it\n        }?.\n        map {\n            it * it\n        }\nval foo2 =\n    listOf(1, 2, 3)\n        .filter {\n            it > 2\n        }\n        .map {\n            2 * it\n        }\n        ?.map {\n            2 * it\n        }\nval foo3 = \n    foo()\n    .bar().map {\n        it.foobar()\n    }\nval foo4 =\n    \"\"\"\n    Some text\n    \"\"\".trimIndent().foo()\n        .bar()\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_thanForce wrapping of chained methods in case an expression contains at least the specified number of chain operators. If a chained method contains nested expressions, the chain operators of the inner expression are not taken into account. Use value unset (default) to disable this setting. 4 4 4 max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:chain-method-continuation

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:chain-method-continuation\")\n
    Enable rule via .editorconfig
    ktlint_standard_chain-method-continuation = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_chain-method-continuation = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#class-signature","title":"Class signature","text":"

Rewrites the class signature to a consistent format respecting the .editorconfig property max_line_length if set. In the ktlint_official code style all class parameters are wrapped by default. Set .editorconfig property ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than to a value greater than 1 to allow classes with a few parameters to be placed on a single line. The other code styles allow an infinite amount of parameters on the same line (as long as the max_line_length is not exceeded) unless .editorconfig property ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than is set explicitly.

Ktlint (ktlint_official) Disallowed (ktlint_official) Ktlint (non ktlint_official) Disallowed (non ktlint_official)
// Assume that max_line_length is not exceeded when written as single line\nclass Foo0\n\nclass Foo1(\n    a: Any,\n)\n\nclass Foo2(\n    a: Any,\n    b: Any,\n)\n\nclass Foo3(\n    @Foo a: Any,\n    b: Any,\n    c: Any,\n)\n\nclass Foo4(\n    a: Any,\n    b: Any,\n    c: Any,\n) : FooBar(a, c)\n\nclass Foo5 :\n    FooBar(\n        \"bar1\",\n        \"bar2\",\n    ) {\n    // body\n}\n\nclass Foo6(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(\n        bar1,\n        bar2,\n    ) {\n    // body\n}\n\nclass Foo7(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(\n        bar1,\n        bar2,\n    ),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n\nclass Foo8\n    constructor(\n        val bar1: Bar,\n        val bar2: Bar,\n    ) : FooBar(bar1, bar2),\n        BarFoo1,\n        BarFoo2 {\n        // body\n    }\n
// Assume that max_line_length is not exceeded when written as single line\nclass Foo0()\n\nclass Foo1(a: Any)\n\nclass Foo2(a: Any, b: Any)\n\nclass Foo3(@Foo a: Any, b: Any, c: Any)\n\nclass Foo4(a: Any, b: Any, c: Any) : FooBar(a, c)\n\nclass Foo5 : FooBar(\n    \"bar1\",\n    \"bar2\",\n) {\n    // body\n}\n\nclass Foo6(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(\n    bar1,\n    bar2,\n) {\n    // body\n}\n\nclass Foo7(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(\n    bar1,\n    bar2,\n),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n\nclass Foo8\nconstructor(\n    val bar1: Bar,\n    val bar2: Bar,\n) : FooBar(bar1, bar2),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Foo0\n\n// Entire class signature does not fit on single line\nclass Foo1(\n    aVeryLonggggggggggggggggggggggg: Any\n)\n\n// Entire class signature does fit on single line\nclass Foo2(a: Any)\n\n// Entire class signature does not fit on single line\nclass Foo3(\n    aVeryLonggggggggggggggg: Any,\n    b: Any\n)\n\n// Entire class signature does fit on single line\nclass Foo4(a: Any, b: Any)\n\n// Entire class signature does fit on single line\nclass Foo5(@Foo a: Any, b: Any, c: Any)\n\n// Entire class signature does fit on single line\nclass Foo6(a: Any, b: Any, c: Any) :\n    FooBar(a, c)\n\n// Entire class signature (without constructor invocation) does fit on single line\nclass Foo7 :\n    FooBar(\n        \"bar1\",\n        \"bar2\"\n    ) {\n    // body\n}\n\n// Entire class signature (without constructor invocation) does fit on single line\nclass Foo8(val bar1: Bar, val bar2: Bar) :\n    FooBar(\n        bar1,\n        bar2\n    ) {\n    // body\n}\n\n// Entire class signature (without constructor invocation) does not fit on single line\nclass Foo9(\n    val aVeryLonggggggggggggggg: Bar,\n    val bar2: Bar\n) : FooBar(\n    bar1,\n    bar2\n) {\n    // body\n}\n\nclass Foo10(val bar1: Bar, val bar2: Bar) :\n    FooBar(\n        bar1,\n        bar2\n    ),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n\nclass Foo11\nconstructor(\n    val bar1: Bar,\n    val bar2: Bar\n) : FooBar(bar1, bar2),\n    BarFoo1,\n    BarFoo2 {\n    // body\n}\n
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Foo0()\n\nclass Foo6(a: Any, b: Any, c: Any) : FooBar(a, c)\n\n// Entire class signature (without constructor invocation) does fit on single line\nclass Foo7 : FooBar(\n    \"bar1\",\n    \"bar2\",\n) {\n    // body\n}\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_thanForce wrapping of the parameters of the class signature in case it contains at least the specified number of parameters, even in case the entire class signature would fit on a single line. Use value unset to disable this setting. 1 unset unset max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:class-signature

Warn

For code styles android_studio and intellij_idea this rule rewrites multiline class signature to a single line class signature in case the entire class signature fits on a single line by default. In case you want to leave it to the discretion of the developer to decider whether a single or a multiline class signature is used, please suppress or disable this rule.

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:class-signature\")\n
    Enable rule via .editorconfig
    ktlint_standard_class-signature = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_class-signature = disabled\n
"},{"location":"rules/standard/#enum-entry","title":"Enum entry","text":"

Enum entry names should be uppercase underscore-separated or upper camel-case separated.

Ktlint Disallowed
enum class Bar {\n    FOO,\n    Foo,\n    FOO_BAR,\n    FooBar,\n}\n
enum class Bar {\n    foo,\n    bAr,\n    Foo_Bar,\n}\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_enum_entry_name_casingChoose any of upper_cases (an enum entry may only contain uppercases, and underscores, and digits, and dicritics on letters and strokes), camel_cases (an enum entry may only contain CamelCase values, including digits, and dicritics on letters and strokes), or upper_or_camel_case (allows mixing of uppercase and CamelCase entries as per Kotlin Coding Conventions). upper_or_camel_cases upper_or_camel_cases upper_or_camel_cases

Rule id: standard:enum-entry-name-case

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:enum-entry-name-case\")\n
    Enable rule via .editorconfig
    ktlint_standard_enum-entry-name-case = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_enum-entry-name-case = disabled\n
"},{"location":"rules/standard/#file-name","title":"File name","text":"

A file containing only one visible (e.g. non-private) class, and visible declarations related to that class only, should be named according to that element. The same applies if the file does not contain a visible class but exactly one type alias or one object declaration. Otherwise, the PascalCase notation should be used.

Rule id: standard:filename

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:filename\")\n
    Enable rule via .editorconfig
    ktlint_standard_filename = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_filename = disabled\n
"},{"location":"rules/standard/#final-newline","title":"Final newline","text":"

Ensures consistent usage of a newline at the end of each file.

Configuration setting ktlint_official intellij_idea android_studio insert_final_newline true true true

Rule id: standard:final-newline

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:final-newline\")\n
    Enable rule via .editorconfig
    ktlint_standard_final-newline = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_final-newline = disabled\n
"},{"location":"rules/standard/#function-expression-body","title":"Function expression body","text":"

Rewrites a function body only containing a return or throw expression to an expression body.

Note

If the function body contains a comment, it is not rewritten to an expression body.

Ktlint Disallowed
fun foo1() = \"foo\"\n\nfun foo2(): String = \"foo\"\n\nfun foo3(): Unit = throw IllegalArgumentException(\"some message\")\n\nfun foo4(): Foo = throw IllegalArgumentException(\"some message\")\n\nfun foo5() {\n    return \"foo\" // some comment\n}\n\nfun foo6(): String {\n    /* some comment */\n    return \"foo\"\n}\n\nfun foo7() {\n    throw IllegalArgumentException(\"some message\")\n    /* some comment */\n}\n\nfun foo8(): Foo {\n    throw IllegalArgumentException(\"some message\")\n    // some comment\n}\n
fun foo1() {\n    return \"foo\"\n}\n\nfun foo2(): String {\n    return \"foo\"\n}\n\nfun foo3() {\n    throw IllegalArgumentException(\"some message\")\n}\n\nfun foo4(): Foo {\n    throw IllegalArgumentException(\"some message\")\n}\n

Rule id: standard:function-expression-body

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-expression-body\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-expression-body = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-expression-body = disabled\n
"},{"location":"rules/standard/#function-literal","title":"Function literal","text":"

Enforces the parameters of a function literal and the arrow to be written on the same line as the opening brace if the maximum line length is not exceeded. In case the parameters are wrapped to multiple lines then this is respected.

If the function literal contains multiple parameters and at least one parameter other than the first parameter starts on a new line than all parameters and the arrow are wrapped to separate lines.

Ktlint (ktlint_official) Ktlint (non ktlint_official) Disallowed
val foobar1 = { foo + bar }\nval foobar2 =\n    {\n        foo + bar\n    }\nval foobar3 =\n    { foo: Foo ->\n        foo.repeat(2)\n    }\nval foobar4 =\n    { foo: Foo, bar: Bar ->\n        foo + bar\n    }\nval foobar5 = { foo: Foo, bar: Bar -> foo + bar }\nval foobar6 =\n    {\n        foo: Foo,\n        bar: Bar,\n        ->\n        foo + bar\n    }\n\n// Assume that the last allowed character is\n// at the X character on the right           X\nval foobar7 =\n    barrrrrrrrrrrrrr { \n        fooooooooooooooo: Foo\n        ->\n        foo.repeat(2)\n    }\n
val foobar6 =\n    {\n            foo: Foo,\n            bar: Bar,\n        ->\n        foo + bar\n    }\n\n// Assume that the last allowed character is\n// at the X character on the right           X\nval foobar7 =\n    barrrrrrrrrrrrrr { \n            fooooooooooooooo: Foo\n        ->\n        foo.repeat(2)\n    }\n
val foobar3 =\n    {\n        foo: Foo ->\n        foo.repeat(2)\n    }\nval foobar6 =\n    { foo: Foo,\n      bar: Bar ->\n        foo + bar\n    }\n// Assume that the last allowed character is\n// at the X character on the right           X\nval foobar7 =\n    barrrrrrrrrrrrrr { fooooooooooooooo: Foo ->\n        foo.repeat(2)\n    }\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:function-literal

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-literal\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-literal = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-literal = disabled\n
"},{"location":"rules/standard/#function-signature","title":"Function signature","text":"

Rewrites the function signature to a single line when possible (e.g. when not exceeding the max_line_length property) or a multiline signature otherwise.

Note

Wrapping of parameters is also influenced by the parameter-list-wrapping rule.

Ktlint Disallowed
// Assume that the last allowed character is\n// at the X character on the right           X\nfun foooooooo(\n    a: Any,\n    b: Any,\n    c: Any,\n): String {\n    // body\n}\n\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun bar(a: Any, b: Any, c: Any): String {\n    // body\n}\n\n// When wrapping of body is set to 'default'.\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun f(a: Any, b: Any): String = \"some-result\"\n    .uppercase()\n\n// When wrapping of body is set to 'multiline'\n// or 'always'.\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun f(a: Any, b: Any): String =\n    \"some-result\"\n        .uppercase()\n
// Assume that the last allowed character is\n// at the X character on the right           X\nfun foooooooo(a: Any, b: Any, c: Any): String {\n    // body\n}\n\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun bar(\n    a: Any,\n    b: Any,\n    c: Any\n): String {\n    // body\n}\n\n// When wrapping of body is set to 'default'.\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun f(a: Any, b: Any): String =\n    \"some-result\"\n        .uppercase()\n\n// When wrapping of body is set to 'multiline'\n// or 'always'.\n// Assume that the last allowed character is\n// at the X character on the right           X\nfun f(a: Any, b: Any): String = \"some-result\"\n    .uppercase()\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_function_signature_body_expression_wrappingDetermines how to wrap the body of function in case it is an expression. Use default to wrap the body expression only when the first line of the expression does not fit on the same line as the function signature. Use multiline to force wrapping of body expressions that consists of multiple lines. Use always to force wrapping of body expression always. multiline default default ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_thanForces a multiline function signature in case the function contains the specified minimum number of parameters even in case the function signature would fit on a single line. Use value unset (default) to disable this setting. 2 unset unset default multiline always

When ktlint_function_signature_body_expression_wrapping is set to default, the first line of a body expression is appended to the function signature as long as the max line length is not exceeded.

ktlint_function_signature_body_expression_wrapping=default
// Given that the function signature has to be written as a single line\n// function signature and that the function has a multiline body expression\nfun someFunction(a: Any, b: Any): String = \"some-result\"\n    .uppercase()\n\n// Given that the function signature has to be written as a multiline\n// function signature and that the function has a multiline body expression\nfun someFunction(\n    a: Any,\n    b: Any\n): String = \"some-result\"\n    .uppercase()\n

When ktlint_function_signature_body_expression_wrapping is set to multiline, the body expression starts on a separate line in case it is a multiline expression. A single line body expression is wrapped only when it does not fit on the same line as the function signature.

ktlint_function_signature_body_expression_wrapping=multiline
// Given that the function signature has to be written as a single line\n// function signature and that the function has a single line body expression\n// that fits on the same line as the function signature.\nfun someFunction(a: Any, b: Any): String = \"some-result\".uppercase()\n\n// Given that the function signature has to be written as a multiline\n// function signature and that the function has a single line body expression\n// that fits on the same line as the function signature.\nfun someFunction(\n    a: Any,\n    b: Any\n): String = \"some-result\".uppercase()\n\n// Given that the function signature has to be written as a single line\n// function signature and that the function has a multiline body expression\nfun someFunction(a: Any, b: Any): String =\n    \"some-result\"\n         .uppercase()\n\n// Given that the function signature has to be written as a multiline\n// function signature and that the function has a multiline body expression\nfun someFunction(\n    a: Any,\n    b: Any\n): String =\n    \"some-result\"\n       .uppercase()\n

When ktlint_function_signature_body_expression_wrapping is set to always the body expression is always wrapped to a separate line.

ktlint_function_signature_body_expression_wrapping=always
// Given that the function signature has to be written as a single line\n// function signature and that the function has a single line body expression\nfun someFunction(a: Any, b: Any): String =\n    \"some-result\".uppercase()\n\n// Given that the function signature has to be written as a multiline\n// function signature and that the function has a multiline body expression\nfun functionWithAVeryLongName(\n    a: Any,\n    b: Any\n): String =\n    \"some-result\"\n        .uppercase()\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:function-signature

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-signature\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-signature = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-signature = disabled\n
"},{"location":"rules/standard/#function-type-modifier-spacing","title":"Function type modifier spacing","text":"

Enforce a single whitespace between the modifier list and the function type.

Ktlint Disallowed
val foo: suspend () -> Unit = {}\n\nsuspend fun bar(baz: suspend () -> Unit) = baz()\n
val foo: suspend() -> Unit = {}\n\nsuspend fun bar(baz: suspend   () -> Unit) = baz()\n

Rule id: standard:function-type-modifier-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-type-modifier-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-type-modifier-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-type-modifier-spacing = disabled\n
"},{"location":"rules/standard/#if-else-bracing","title":"If else bracing","text":"

If at least one branch of an if-else statement or an if-else-if statement is wrapped between curly braces then all branches should be wrapped between braces.

Ktlint Disallowed
fun foo(value: Int) {\n    if (value > 0) {\n        doSomething()\n    } else if (value < 0) {\n        doSomethingElse()\n    } else {\n        doSomethingElse2()\n    }\n}\n
fun foo(value: Int) {\n    if (value > 0)\n        doSomething()\n    else if (value < 0) {\n        doSomethingElse()\n    } else\n        doSomethingElse2()\n}\n

Rule id: standard:if-else-bracing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:if-else-bracing\")\n
    Enable rule via .editorconfig
    ktlint_standard_if-else-bracing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_if-else-bracing = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#import-ordering","title":"Import ordering","text":"

Ensures that imports are ordered consistently (see Import Layouts for configuration).

Ktlint Disallowed
import com.bar.Bar\nimport com.foo.Foo\nimport org.foo.bar.FooBar\nimport java.util.concurrent.ConcurrentHashMap\n
import com.bar.Bar\nimport java.util.concurrent.ConcurrentHashMap\nimport org.foo.bar.FooBar\nimport com.foo.Foo\n

Rule id: standard:import-ordering

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:import-ordering\")\n
    Enable rule via .editorconfig
    ktlint_standard_import-ordering = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_import-ordering = disabled\n
"},{"location":"rules/standard/#indentation","title":"Indentation","text":"

Indentation formatting - respects .editorconfig indent_size with no continuation indent (see EditorConfig section for more).

Ktlint Disallowed
fun main() {\n    foobar(\n        a,\n        b,\n        c,\n    )\n}\n
fun main() {\n    foobar(\n          a,\n          b,\n          c,\n          )\n}\n

Note

This rule handles indentation for many different language constructs which can not be summarized with a few examples. See the unit tests for more details.

Configuration setting ktlint_official intellij_idea android_studio indent_sizeThe size of an indentation level when indent_style is set to space. Use value unset to ignore indentation. 4 4 4 indent_styleStyle of indentation. Set this value to space or tab. space space space ij_kotlin_indent_before_arrow_on_new_lineIndent the arrow in a when-entry if the arrow starts on a new line. Set this value to true or false. Starting from IDEA version 2024.2 or above this value needs to be set to true to maintain compatibility with IDEA formatting. false false false

Rule id: standard:indent

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:indent\")\n
    Enable rule via .editorconfig
    ktlint_standard_indent = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_indent = disabled\n
"},{"location":"rules/standard/#naming","title":"Naming","text":""},{"location":"rules/standard/#backing-property-naming","title":"Backing property naming","text":"

Allows property names to start with _ in case the property is a backing property. ktlint_official and android_studio code styles require the correlated property/function to be defined as public.

Ktlint Disallowed
class Bar {\n    // Backing property\n    private val _elementList = mutableListOf<Element>()\n    val elementList: List<Element>\n        get() = _elementList\n}\n
class Bar {\n    // Incomplete backing property as public property 'elementList1' is missing\n    private val _elementList1 = mutableListOf<Element>()\n\n    // Invalid backing property as '_elementList2' is not a private property\n    val _elementList2 = mutableListOf<Element>()\n    val elementList2: List<Element>\n        get() = _elementList2\n}\n

Rule id: standard:backing-property-naming

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:backing-property-naming\")\n
    Enable rule via .editorconfig
    ktlint_standard_backing-property-naming = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_backing-property-naming = disabled\n
"},{"location":"rules/standard/#class-naming","title":"Class naming","text":"

Enforce naming of class and objects.

Ktlint Ktlint JUnit Test Disallowed
class Foo\n\nclass Foo1\n\nclass `class` // Any keyword is allowed when wrapped between backticks\n
@Nested\ninner class `Some descriptive class name` {\n    @Test\n    fun `Some descriptive test name`() {\n        // do something\n    }\n}\n
class foo\nclass Foo_Bar\nclass `Some class in the production code`\n

Note

Functions in files which import a class from package org.junit.jupiter.api are considered to be test functions and are allowed to have a name specified between backticks and do not need to adhere to the normal naming convention. Although, the Kotlin coding conventions does not allow this explicitly for class identifiers, ktlint does allow it.

This rule can also be suppressed with the IntelliJ IDEA inspection suppression ClassName.

Rule id: standard:class-naming

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:class-naming\")\n
    Enable rule via .editorconfig
    ktlint_standard_class-naming = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_class-naming = disabled\n
"},{"location":"rules/standard/#function-naming","title":"Function naming","text":"

Enforce naming of function.

Ktlint Ktlint Test Disallowed
fun foo() {}\n\nfun fooBar() {}\n\nfun `fun`() {} // Any keyword is allowed when wrapped between backticks\n
@Test\nfun `Some name`() {}\n\n@Test\nfun do_something() {}\n
fun Foo() {}\nfun Foo_Bar() {}\nfun `Some name`() {}\nfun do_something() {}\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_function_naming_ignore_when_annotated_withIgnore functions that are annotated with values in this setting. This value is a comma separated list of names without the '@' prefix. unset unset unset

Note

When using Compose, you might want to configure the function-naming rule with .editorconfig property ktlint_function_naming_ignore_when_annotated_with=Composable. Furthermore, you can use a dedicated ktlint ruleset like Compose Rules for checking naming conventions for Composable functions.

Note

Functions in files which import a class from package io.kotest, junit.framework, kotlin.test, org.junit, or org.testng are considered to be test functions. Functions in such classes are allowed to have underscores in the name. Also, function names enclosed between backticks do not need to adhere to the normal naming convention.

This rule can also be suppressed with the IntelliJ IDEA inspection suppression FunctionName.

Rule id: standard:function-naming

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-naming\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-naming = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-naming = disabled\n
"},{"location":"rules/standard/#package-name","title":"Package name","text":"

Validates that the package name matches the regular expression [a-z][a-zA-Z\\d]*(\\.[a-z][a-zA-Z\\d]*)*.

Ktlint Disallowed
package foo\npackage foo.bar\n
package Foo\npackage foo.Foo\npackage `foo bar`\npackage foo.`foo bar`\n

Rule id: standard:package-name

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:package-name\")\n
    Enable rule via .editorconfig
    ktlint_standard_package-name = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_package-name = disabled\n
"},{"location":"rules/standard/#property-naming","title":"Property naming","text":"

Enforce naming of property.

Note

This rule can not reliably detect all situations in which incorrect property naming is used. So it only detects in which it is certain that naming is incorrect.

Ktlint Disallowed
val foo1 = Foo() // In case developers want to tell that Foo is mutable\nval FOO1 = Foo() // In case developers want to tell that Foo is deeply immutable\n\nconst val FOO_BAR = \"FOO-BAR\" // By definition deeply immutable\n\nvar foo2: Foo = Foo() // By definition not immutable\n\nclass Bar {\n    val foo1 = \"foo1\" // Class properties always start with lowercase, const is not allowed\n\n    const val FOO_BAR = \"FOO-BAR\" // By definition deeply immutable\n\n    var foo2: Foo = Foo() // By definition not immutable\n\n    // Backing property\n    private val _elementList = mutableListOf<Element>()\n    val elementList: List<Element>\n        get() = _elementList\n\n    companion object {\n        val foo1 = Foo() // In case developer want to communicate that Foo is mutable\n        val FOO1 = Foo() // In case developer want to communicate that Foo is deeply immutable\n    }\n}\n\nvar `package` = \"foo\" // Any keyword is allowed when wrapped between backticks\n
const val fooBar = \"FOO-BAR\" // By definition deeply immutable\n\nvar FOO2: Foo = Foo() // By definition not immutable\n\nclass Bar {\n    val FOO_BAR = \"FOO-BAR\" // Class properties always start with lowercase, const is not allowed\n\n    // Incomplete backing property as public property 'elementList1' is missing\n    private val _elementList1 = mutableListOf<Element>()\n\n    // Invalid backing property as '_elementList2' is not a private property\n    val _elementList2 = mutableListOf<Element>()\n    val elementList2: List<Element>\n        get() = _elementList2\n}\n

This rule is suppressed whenever the IntelliJ IDEA inspection suppression PropertyName, ConstPropertyName, ObjectPropertyName or PrivatePropertyName is used.

Rule id: standard:property-naming

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:property-naming\")\n
    Enable rule via .editorconfig
    ktlint_standard_property-naming = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_property-naming = disabled\n
"},{"location":"rules/standard/#no-blank-lines-in-list","title":"No blank lines in list","text":"

Disallow blank lines to be used in lists before the first element, between elements, and after the last element.

Super type

Ktlint Disallowed
class FooBar :\n    Foo,\n    Bar {\n    // body\n}\n
class FooBar :\n\n    Foo,\n\n    Bar\n\n{\n    // body\n}\n

Type argument list

Ktlint Disallowed
val foobar: FooBar<\n    Foo,\n    Bar,\n    > = FooBar(Foo(), Bar())\n
val foobar: FooBar<\n\n    Foo,\n\n    Bar,\n\n    > = FooBar(Foo(), Bar())\n

Type constraint list

Ktlint Disallowed
class BiAdapter<C : RecyclerView.ViewHolder, V1 : C, V2 : C, out A1, out A2>(\n    val adapter1: A1,\n    val adapter2: A2,\n) : RecyclerView.Adapter<C>()\n    where A1 : RecyclerView.Adapter<V1>, A1 : ComposableAdapter.ViewTypeProvider,\n          A2 : RecyclerView.Adapter<V2>, A2 : ComposableAdapter.ViewTypeProvider {\n    // body\n}\n
class BiAdapter<C : RecyclerView.ViewHolder, V1 : C, V2 : C, out A1, out A2>(\n    val adapter1: A1,\n    val adapter2: A2\n) : RecyclerView.Adapter<C>()\n    where\n          A1 : RecyclerView.Adapter<V1>, A1 : ComposableAdapter.ViewTypeProvider,\n\n          A2 : RecyclerView.Adapter<V2>, A2 : ComposableAdapter.ViewTypeProvider\n{\n    // body\n}\n

Type parameter list

Ktlint Disallowed
fun <\n    Foo,\n    Bar,\n    > foobar()\n
fun <\n\n    Foo,\n\n    Bar,\n\n    > foobar()\n

Value argument list

Ktlint Disallowed
val foobar =\n    foobar(\n        \"foo\",\n        \"bar\",\n    )\n
val foobar = \n    foobar(\n\n      \"foo\",\n\n      \"bar\",\n\n  )\n

Value parameter list

Ktlint Disallowed
fun foobar(\n    foo: String,\n    bar: String,\n)\n
fun foobar(\n\n    foo: String,\n\n    bar: String,\n\n)\n

Rule id: standard:no-blank-line-in-list

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-blank-line-in-list\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-blank-line-in-list = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-blank-line-in-list = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#no-consecutive-comments","title":"No consecutive comments","text":"

Consecutive comments are disallowed in following cases: - Any mix of a consecutive kdoc, a block comment or an EOL comment unless separated by a blank line in between - Consecutive KDocs (even when separated by a blank line) - Consecutive block comments (even when separated by a blank line)

Consecutive EOL comments are always allowed as they are often used instead of a block comment.

Ktlint Disallowed
// An EOL comment\n// may be followed by another EOL comment\nval foo = \"foo\"\n\n// Different comment types (including KDoc) may be consecutive ..\n\n/*\n * ... but do need to be separated by a blank line ...\n */\n\n/**\n  * ... but a KDoc can not be followed by an EOL or a block comment or another KDoc\n  */\nfun bar() = \"bar\"\n
/*\n * Block comments can not be consecutive ...\n */\n/*\n * ... even not when separated by a new line.\n */\nval bar = \"bar\" \n\n/**\n  * A KDoc can not be followed by a block comment or an EOL comment or another KDOC\n  */\n\n// ... even not when separated by a new line.\n

Rule id: standard:no-consecutive-comments

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-consecutive-comments\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-consecutive-comments = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-consecutive-comments = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#no-empty-file","title":"No empty file","text":"

A kotlin (script) file should not be empty. It needs to contain at least one declaration. Files only contain a package and/or import statements are as of that disallowed.

Rule id: standard:no-empty-file

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-empty-file\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-empty-file = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-empty-file = disabled\n
"},{"location":"rules/standard/#no-empty-first-line-at-start-in-class-body","title":"No empty first line at start in class body","text":"

Detect blank lines at start of a class body.

Ktlint Disallowed
class Foo {\n    val foo = \"foo\"\n}\n
class Foo {\n\n    val foo = \"foo\"\n}\n

Rule id: standard:no-empty-first-line-in-class-body

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-empty-first-line-in-class-body\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-empty-first-line-in-class-body = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-empty-first-line-in-class-body = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#no-single-line-block-comment","title":"No single line block comment","text":"

A single line block comment should be replaced with an EOL comment when possible.

Ktlint Disallowed
/*\n * Some comment\n */\nval foo = \"foo\" // Some comment\nval foo = { /* no-op */ }\n
/* Some comment */\nval foo = \"foo\" /* Some comment */\n

Rule id: standard:no-single-line-block-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-single-line-block-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-single-line-block-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-single-line-block-comment = disabled\n
"},{"location":"rules/standard/#ktlint-suppression-rule","title":"Ktlint-suppression rule","text":"

The ktlint-disable and ktlint-enable directives are no longer supported as of ktlint version 0.50.0. This rule migrates the directives to Suppress or SuppressWarnings annotations.

Identifiers in the @Suppress and @SuppressWarnings annotations to suppress ktlint rules are checked for validity and autocorrected when possible.

Ktlint Disallowed
@file:Suppress(\"ktlint:standard:no-wildcard-imports\")\n\nclass FooBar {\n    @Suppress(\"ktlint:standard:max-line-length\")\n    val foo = \"some longggggggggggggggggggg text\"\n\n    fun bar() =\n        @Suppress(\"ktlint:standard:no-multi-spaces\")\n        listOf(\n            \"1   One\", \n            \"10  Ten\", \n            \"100 Hundred\", \n        )\n}\n
/* ktlint-disable standard:no-wildcard-imports */\n\nclass FooBar {\n    val foo = \"some longggggggggggggggggggg text\" // ktlint-disable standard:max-line-length\n\n    fun bar() =\n        listOf(\n            /* ktlint-disable standard:no-multi-spaces */\n            \"1   One\", \n            \"10  Ten\", \n            \"100 Hundred\", \n            /* ktlint-enable standard:no-multi-spaces */\n        )\n}\n

Rule id: standard:ktlint-suppression

Note

This rule cannot be suppressed via @Suppress or be disabled in the .editorconfig.

"},{"location":"rules/standard/#max-line-length","title":"Max line length","text":"

Ensures that lines do not exceed the maximum length of a line as specified in .editorconfig property max_line_length.

This rule does not apply in a number of situations. The .editorconfig property ktlint_ignore_back_ticked_identifier can be set to ignore identifiers which are enclosed in backticks, which for example is very useful when you want to allow longer names for unit tests.

Ktlint Disallowed
// Assume that the last allowed character is\n// at the X character on the right           X\n// Lines below are accepted although the max\n// line length is exceeded.\npackage com.toooooooooooooooooooooooooooo.long\nimport com.tooooooooooooooooooooooooooooo.long\n\nval foo1 =\n    \"\"\"\n    fooooooooooooooooooooooooooooooooooooooooo\n    \"\"\"\n\nval foo2 =\n    \"fooooooooooooooooooooooooooooooooooooooo\"\n\n@Test\nfun `Test description which is toooooooooooo long`() {\n}\n
// Assume that the last allowed character is\n// at the X character on the right           X\nval fooooooooooooooo = \"fooooooooooooooooooooo\"\nval foo = \"foo\" + \"ooooooooooooooooooooooooooo\"\nval foooooooooooooo = \"foooooooooooooooooooo\" // some comment\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_ignore_back_ticked_identifierDefines whether the backticked identifier (``) should be ignored. false false false max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:max-line-length

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:max-line-length\")\n
    Enable rule via .editorconfig
    ktlint_standard_max-line-length = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_max-line-length = disabled\n
"},{"location":"rules/standard/#modifier-order","title":"Modifier order","text":"

Consistent order of modifiers

Ktlint Disallowed
abstract class A {\n    protected open val v = \"\"\n\n    internal open suspend fun f(v: Any): Any = \"\"\n\n    protected lateinit var lv: String\n}\n
abstract class A {\n    open protected val v = \"\"\n\n    open suspend internal fun f(v: Any): Any = \"\"\n\n    lateinit protected var lv: String\n}\n

Rule id: standard:modifier-order

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:modifier-order\")\n
    Enable rule via .editorconfig
    ktlint_standard_modifier-order = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_modifier-order = disabled\n
"},{"location":"rules/standard/#multiline-if-else","title":"Multiline if-else","text":"

Braces required for multiline if/else statements.

Ktlint Disallowed
val foo =\n    if (true) {\n        return 0\n    } else {\n        return 1\n    }\n
val foo =\n    if (true)\n        return 0\n    else\n        return 1\n

Rule id: standard:multiline-if-else

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:multiline-if-else\")\n
    Enable rule via .editorconfig
    ktlint_standard_multiline-if-else = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_multiline-if-else = disabled\n
"},{"location":"rules/standard/#multiline-loop","title":"Multiline loop","text":"

Braces required for multiline for, while, and do statements.

Ktlint Disallowed
for (i in 1..10) {\n    println(i)\n}\n
for (i in 1..10)\n    println(i)\n

Rule id: standard:multiline-loop

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:multiline-loop\")\n
    Enable rule via .editorconfig
    ktlint_standard_multiline-loop = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_multiline-loop = disabled\n
"},{"location":"rules/standard/#no-blank-lines-before","title":"No blank lines before }","text":"

No blank lines before }.

Ktlint Disallowed
fun main() {\n    fun a() {\n    }\n\n    fun b()\n}\n
fun main() {\n    fun a() {\n\n    }\n    fun b()\n\n}\n

Rule id: standard:no-blank-line-before-rbrace

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-blank-line-before-rbrace\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-blank-line-before-rbrace = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-blank-line-before-rbrace = disabled\n
"},{"location":"rules/standard/#no-blank-lines-in-chained-method-calls","title":"No blank lines in chained method calls","text":"Ktlint Disallowed
fun foo(inputText: String) {\n    inputText\n        .lowercase(Locale.getDefault())\n}\n
fun foo(inputText: String) {\n    inputText\n\n        .lowercase(Locale.getDefault())\n}\n

Rule id: standard:no-blank-lines-in-chained-method-calls

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-blank-lines-in-chained-method-calls\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-blank-lines-in-chained-method-calls = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-blank-lines-in-chained-method-calls = disabled\n
"},{"location":"rules/standard/#no-consecutive-blank-lines","title":"No consecutive blank lines","text":"Ktlint Disallowed
package com.test\n\nimport com.test.util\n\nval a = \"a\"\n\nfun b() {\n}\n\nfun c()\n
package com.test\n\n\nimport com.test.util\n\n\nval a = \"a\"\n\n\nfun b() {\n}\n\n\nfun c()\n

Rule id: standard:no-consecutive-blank-lines

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-consecutive-blank-lines\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-consecutive-blank-lines = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-consecutive-blank-lines = disabled\n
"},{"location":"rules/standard/#no-empty-class-bodies","title":"No empty ({}) class bodies","text":"Ktlint Disallowed
class C\n\ndata class DC(val v: Any)\n\ninterface I\n\nobject O\n
class C {}\n\ndata class DC(val v: Any) { }\n\ninterface I {\n}\n\nobject O{}\n

Rule id: standard:no-empty-class-body

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-empty-class-body\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-empty-class-body = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-empty-class-body = disabled\n
"},{"location":"rules/standard/#no-leading-empty-lines-in-method-blocks","title":"No leading empty lines in method blocks","text":"Ktlint Disallowed
fun bar() {\n   val a = 2\n}\n
fun bar() {\n\n   val a = 2\n}\n

Rule id: standard:no-empty-first-line-in-method-block

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-empty-first-line-in-method-block\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-empty-first-line-in-method-block = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-empty-first-line-in-method-block = disabled\n
"},{"location":"rules/standard/#no-line-break-after-else","title":"No line break after else","text":"

Disallows line breaks after the else keyword if that could lead to confusion, for example:

Ktlint Disallowed
fun funA() {\n    if (conditionA()) {\n        doSomething()\n    } else if (conditionB()) {\n        doAnotherThing()\n    }\n}\n
fun funA() {\n    if (conditionA()) {\n        doSomething()\n    } else\n    if (conditionB()) {\n        doAnotherThing()\n    }\n}\n

Rule id: standard:no-line-break-after-else

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-line-break-after-else\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-line-break-after-else = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-line-break-after-else = disabled\n
"},{"location":"rules/standard/#no-line-break-before-assignment","title":"No line break before assignment","text":"

When a line is broken at an assignment (=) operator the break comes after the symbol.

Ktlint Disallowed
val valA =\n    \"\"\n
val valA\n    = \"\"\n

Rule id: standard:no-line-break-before-assignment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-line-break-before-assignment\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-line-break-before-assignment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-line-break-before-assignment = disabled\n
"},{"location":"rules/standard/#no-multi-spaces","title":"No multi spaces","text":"

Except in indentation and in KDoc's it is not allowed to have multiple consecutive spaces.

Ktlint Disallowed
fun main() {\n    x(1, 3)\n}\n
fun  main()  {\n    x(1,  3)\n}\n

Rule id: standard:no-multi-spaces

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-multi-spaces\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-multi-spaces = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-multi-spaces = disabled\n
"},{"location":"rules/standard/#no-semicolons","title":"No semicolons","text":"

Avoid using unnecessary semicolons.

Ktlint Disallowed
fun foo() {\n    bar()\n\n    bar()\n}\n
fun foo() {\n    ;\n    bar()\n    ;\n\n    bar()\n\n    ;\n}\n

Rule id: standard:no-semi

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-semi\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-semi = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-semi = disabled\n
"},{"location":"rules/standard/#no-trailing-whitespaces","title":"No trailing whitespaces","text":"

Rule id: standard:no-trailing-spaces

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-trailing-spaces\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-trailing-spaces = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-trailing-spaces = disabled\n
"},{"location":"rules/standard/#no-unit-as-return-type","title":"No Unit as return type","text":"

The Unit type is not allowed as return-type of a function.

Ktlint Disallowed
fun fn() {}\n
fun fn(): Unit {}\n

Rule id: standard:no-unit-return

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-unit-return\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-unit-return = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-unit-return = disabled\n
"},{"location":"rules/standard/#no-unused-imports","title":"No unused imports","text":"

Warning

This rule is not able to detect all unused imports as mentioned in this issue comment.

Rule id: standard:no-unused-imports

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-unused-imports\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-unused-imports = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-unused-imports = disabled\n
"},{"location":"rules/standard/#no-wildcard-imports","title":"No wildcard imports","text":"

No wildcard imports except whitelisted imports.

Ktlint Disallowed
import foobar.Bar\nimport foobar.Foo\n
import foobar.*\n
Configuration setting ktlint_official intellij_idea android_studio ij_kotlin_packages_to_use_import_on_demandDefines allowed wildcard imports as a comma separated list. - java.util.*,kotlinx.android.synthetic.** java.util.*,kotlinx.android.synthetic.**

Warning

In case property ij_kotlin_packages_to_use_import_on_demand is not explicitly set, Intellij IDEA allows wildcards imports like java.util.* which lead to conflicts with the no-wildcard-imports rule. See Intellij IDEA configuration to prevent such conflicts.

Configuration setting ij_kotlin_packages_to_use_import_on_demand is a comma separated string of import paths. This can be a full path, e.g. \"java.util.List.\", or a wildcard path, e.g. \"kotlin.\". Use \"*\" as wildcard for package and all subpackages.

The layout can be composed by the following symbols:

Examples:

ij_kotlin_imports_layout=* # alphabetical with capital letters before lower case letters (e.g. Z before a), no blank lines\nij_kotlin_imports_layout=*,java.**,javax.**,kotlin.**,^ # default IntelliJ IDEA style, same as alphabetical, but with \"java\", \"javax\", \"kotlin\" and alias imports in the end of the imports list\nij_kotlin_imports_layout=android.**,|,^org.junit.**,kotlin.io.Closeable.*,|,*,^ # custom imports layout\n

Rule id: standard:no-wildcard-imports

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:no-wildcard-imports\")\n
    Enable rule via .editorconfig
    ktlint_standard_no-wildcard-imports = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_no-wildcard-imports = disabled\n
"},{"location":"rules/standard/#spacing","title":"Spacing","text":""},{"location":"rules/standard/#angle-bracket-spacing","title":"Angle bracket spacing","text":"

No spaces around angle brackets when used for typing.

Ktlint Disallowed
val a: Map<Int, String> = mapOf()\nval b: Map<Int, String> = mapOf()\nval c: Map<Int, String> = mapOf()\n
val a: Map< Int, String> = mapOf()\nval b: Map<Int, String > = mapOf()\nval c: Map <Int, String> = mapOf()\n

Rule id: standard:spacing-around-angle-brackets

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:spacing-around-angle-brackets\")\n
    Enable rule via .editorconfig
    ktlint_standard_spacing-around-angle-brackets = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_spacing-around-angle-brackets = disabled\n
"},{"location":"rules/standard/#annotation-spacing","title":"Annotation spacing","text":"

Annotations should be separated by a single line break.

Ktlint Disallowed
@JvmField\nfun foo() {}\n\n/**\n * block comment\n */\n@Foo @Bar\nclass FooBar {\n}\n
@JvmField\n\nfun foo() {}\n\n@Foo @Bar\n/**\n * block comment\n */\nclass FooBar {\n}\n

Rule id: standard:annotation-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:annotation-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_annotation-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_annotation-spacing = disabled\n
"},{"location":"rules/standard/#blank-line-between-declarations-with-annotations","title":"Blank line between declarations with annotations","text":"

Declarations with annotations should be separated by a blank line.

Ktlint Disallowed
fun a()\n\n@Bar\nfun b()\n
fun a()\n@Bar\nfun b()\n

Rule id: standard:spacing-between-declarations-with-annotations

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:spacing-between-declarations-with-annotations\")\n
    Enable rule via .editorconfig
    ktlint_standard_spacing-between-declarations-with-annotations = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_spacing-between-declarations-with-annotations = disabled\n
"},{"location":"rules/standard/#blank-line-between-declaration-with-comments","title":"Blank line between declaration with comments","text":"

Declarations with comments should be separated by a blank line.

Ktlint Disallowed
// some comment 1\nbar()\n\n/*\n * some comment 2\n */\nfoo()\n
// some comment 1\nbar()\n/*\n * some comment 2\n */\nfoo()\n

Rule id: standard:spacing-between-declarations-with-comments

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:spacing-between-declarations-with-comments\")\n
    Enable rule via .editorconfig
    ktlint_standard_spacing-between-declarations-with-comments = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_spacing-between-declarations-with-comments = disabled\n
"},{"location":"rules/standard/#colon-spacing","title":"Colon spacing","text":"

Consistent spacing around colon.

Ktlint Disallowed
class A : B\n\nclass A2 : B2\n
class A:B\n\nclass A2  :  B2\n

Rule id: standard:colon-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:colon-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_colon-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_colon-spacing = disabled\n
"},{"location":"rules/standard/#comma-spacing","title":"Comma spacing","text":"

Consistent spacing around comma.

Ktlint Disallowed
val foo1 = Foo(1, 3)\nval foo2 = Foo(1, 3)\n
val foo1 = Foo(1 ,3)\nval foo2 = Foo(1,3)\n

Rule id: standard:comma-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:comma-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_comma-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_comma-spacing = disabled\n
"},{"location":"rules/standard/#comment-spacing","title":"Comment spacing","text":"

The end of line comment sign // should be preceded and followed by exactly a space.

Ktlint Disallowed
// comment\nvar debugging = false // comment\nvar debugging = false // comment\nvar debugging = false // comment\n\nfun main() {\n    System.out.println(\n        // comment\n        \"test\",\n    )\n} // comment\n
//comment\nvar debugging = false// comment\nvar debugging = false //comment\nvar debugging = false//comment\n\nfun main() {\n    System.out.println(\n         //123\n        \"test\"\n    )\n}//comment\n

Rule id: standard:comment-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:comment-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_comment-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_comment-spacing = disabled\n
"},{"location":"rules/standard/#curly-spacing","title":"Curly spacing","text":"

Consistent spacing around curly braces.

Ktlint Disallowed
val foo = bar { foo() }\n
val foo = bar{foo()}\n

Rule id: standard:curly-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:curly-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_curly-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_curly-spacing = disabled\n
"},{"location":"rules/standard/#dot-spacing","title":"Dot spacing","text":"

Consistent spacing around dots.

Ktlint Disallowed
fun String.foo() = \"foo\"\n
fun String . foo() = \"foo\"\n

Rule id: standard:dot-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:dot-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_dot-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_dot-spacing = disabled\n
"},{"location":"rules/standard/#double-colon-spacing","title":"Double colon spacing","text":"

No spaces around ::.

Ktlint Disallowed
val foo = Foo::class\n
val foo1 = Foo ::class\nval foo2 = Foo:: class\nval foo3 = Foo :: class\nval foo4 = Foo::\n    class\n

Rule id: standard:double-colon-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:double-colon-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_double-colon-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_double-colon-spacing = disabled\n
"},{"location":"rules/standard/#function-return-type-spacing","title":"Function return type spacing","text":"

Consistent spacing around the function return type.

Ktlint Disallowed
fun foo(): String = \"some-result\"\n
fun foo1() : String = \"some-result\"\n\nfun foo2():  String = \"some-result\"\n\nfun foo3():String = \"some-result\"\n\nfun foo4():\n    String = \"some-result\"\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:function-return-type-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-return-type-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-return-type-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-return-type-spacing = disabled\n
"},{"location":"rules/standard/#function-start-of-body-spacing","title":"Function start of body spacing","text":"

Consistent spacing before start of function body.

Ktlint Disallowed
// In case `ktlint_function_signature_body_expression_wrapping` is set to `default` or `multiline`\nfun foo1() = \"some-result\"\n\n// In case `ktlint_function_signature_body_expression_wrapping` is set to `always`\nfun foo2() =\n    \"some-result\"\n\nfun foo3() {\n    // do something\n}\n\n// In case `ktlint_function_signature_body_expression_wrapping` is set to `default` or `multiline`\nfun bar1(): String = \"some-result\"\n\n// In case `ktlint_function_signature_body_expression_wrapping` is set to `always`\nfun bar2(): String =\n    \"some-result\"\n\nfun bar3(): String {\n    doSomething()\n    return \"some-result\"\n}\n
fun foo1()= \"some-result\"\n\nfun foo2()\n    = \"some-result\"\n\nfun foo3()\n{\n    // do something\n}\n\nfun bar1(): String= \"some-result\"\n\nfun bar2(): String\n    = \"some-result\"\n\nfun bar3(): String\n{\n    return \"some-result\"\n}\n

Rule id: standard:function-start-of-body-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-start-of-body-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-start-of-body-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-start-of-body-spacing = disabled\n
"},{"location":"rules/standard/#function-type-reference-spacing","title":"Function type reference spacing","text":"

Consistent spacing in the type reference before a function.

Ktlint Disallowed
fun String.foo() = \"some-result\"\n
fun String .foo() = \"some-result\"\nfun String\n    .foo() = \"some-result\"\nfun String? .foo() = \"some-result\"\nfun String?\n    .foo() = \"some-result\"\n

Rule id: standard:function-type-reference-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:function-type-reference-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_function-type-reference-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_function-type-reference-spacing = disabled\n
"},{"location":"rules/standard/#fun-keyword-spacing","title":"Fun keyword spacing","text":"

Consistent spacing after the fun keyword.

Ktlint Disallowed
fun foo() = \"some-result\"\n
fun  foo() = \"some-result\"\nfun\nfoo() = \"some-result\"\n

Rule id: standard:fun-keyword-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:fun-keyword-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_fun-keyword-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_fun-keyword-spacing = disabled\n
"},{"location":"rules/standard/#kdoc-wrapping","title":"Kdoc wrapping","text":"

A KDoc comment should start and end on a line that does not contain any other element.

Ktlint Disallowed
/** Some KDoc comment 1 */\nval foo1 = \"foo1\"\n
/** Some KDoc comment 1 */ val foo1 = \"foo1\"\nval foo2 = \"foo2\" /** Some KDoc comment\n                   * with a newline\n                   */\n

Rule id: standard:kdoc-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:kdoc-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_kdoc-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_kdoc-wrapping = disabled\n
"},{"location":"rules/standard/#keyword-spacing","title":"Keyword spacing","text":"

Consistent spacing around keywords.

Ktlint Disallowed
fun main() {\n    if (true) {\n        doSomething()\n    }\n}\n
fun main() {\n    if(true) {\n        doSomething()\n    }\n}\n

Rule id: standard:keyword-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:keyword-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_keyword-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_keyword-spacing = disabled\n
"},{"location":"rules/standard/#modifier-list-spacing","title":"Modifier list spacing","text":"

Consistent spacing between modifiers in and after the last modifier in a modifier list.

Ktlint Disallowed
abstract class Foo {\n    protected abstract suspend fun execute()\n}\n
abstract  class Foo {\n    protected  abstract  suspend  fun execute()\n}\nabstract\nclass Foo {\n    protected\n    abstract\n    suspend\n    fun execute()\n}\n

Rule id: standard:modifier-list-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:modifier-list-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_modifier-list-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_modifier-list-spacing = disabled\n
"},{"location":"rules/standard/#nullable-type-spacing","title":"Nullable type spacing","text":"

No spaces in a nullable type.

Ktlint Disallowed
val foo: String? = null\nval foo: List<String?> = listOf(null)\n
val foo: String ? = null\nval foo: List<String ?> = listOf(null)\n

Rule id: standard:nullable-type-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:nullable-type-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_nullable-type-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_nullable-type-spacing = disabled\n
"},{"location":"rules/standard/#operator-spacing","title":"Operator spacing","text":"

Consistent spacing around operators.

Ktlint Disallowed
val foo1 = 1 + 2\nval foo2 = 1 - 2\nval foo3 = 1 * 2\nval foo4 = 1 / 2\n
val foo1 = 1+2\nval foo2 = 1- 2\nval foo3 = 1 *2\nval foo4 = 1  /  2\n

Rule id: standard:op-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:op-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_op-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_op-spacing = disabled\n
"},{"location":"rules/standard/#parameter-list-spacing","title":"Parameter list spacing","text":"

Consistent spacing inside the parameter list.

Ktlint Disallowed
fun foo(a: Any) = \"some-result\"\n\nfun foo() = \"some-result\"\n
fun foo( a : Any ) = \"some-result\"\nfun foo(\n) = \"some-result\"\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:parameter-list-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:parameter-list-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_parameter-list-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_parameter-list-spacing = disabled\n
"},{"location":"rules/standard/#parenthesis-spacing","title":"Parenthesis spacing","text":"

Consistent spacing around parenthesis.

Ktlint Disallowed
class Foo : Bar {\n    constructor(string: String) : super()\n}\n\nval foo1 = ((1 + 2) / 3)\n
class Foo : Bar {\n    constructor(string: String) : super ()\n}\n\nval foo1 = ( (1 + 2 ) / 3)\n

Rule id: standard:paren-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:paren-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_paren-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_paren-spacing = disabled\n
"},{"location":"rules/standard/#range-spacing","title":"Range spacing","text":"

Consistent spacing around range operators.

Ktlint Disallowed
val foo1 = (1..12 step 2).last\nval foo2 = (1..12 step 2).last\nval foo3 = (1..12 step 2).last\n
val foo1 = (1.. 12 step 2).last\nval foo2 = (1 .. 12 step 2).last\nval foo3 = (1 ..12 step 2).last\n

Rule id: standard:range-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:range-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_range-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_range-spacing = disabled\n
"},{"location":"rules/standard/#spacing-between-function-name-and-opening-parenthesis","title":"Spacing between function name and opening parenthesis","text":"

Consistent spacing between function name and opening parenthesis.

Ktlint Disallowed
fun foo() = \"foo\"\n
fun foo () = \"foo\"\n

Rule id: standard:spacing-between-function-name-and-opening-parenthesis

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:spacing-between-function-name-and-opening-parenthesis\")\n
    Enable rule via .editorconfig
    ktlint_standard_spacing-between-function-name-and-opening-parenthesis = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_spacing-between-function-name-and-opening-parenthesis = disabled\n
"},{"location":"rules/standard/#try-catch-finally-spacing","title":"Try catch finally spacing","text":"

Enforce consistent spacing in try { .. } catch { .. } finally { .. }.

Ktlint Disallowed
fun foo() =\n    try {\n        // do something\n    } catch (exception: Exception) {\n        // handle exception\n    } finally {\n        // clean up\n    }\n
fun foo1() = try { /* ... */ } catch (exception: Exception) { /* ... */ } finally { /* ... */ }\nfun foo2() = \n    try {\n        // do something\n    }\n    catch (exception: Exception) {\n        // handle exception\n    }\n    finally {\n        // clean up\n    }\n

Rule id: standard:try-catch-finally-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:try-catch-finally-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_try-catch-finally-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_try-catch-finally-spacing = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#type-argument-list-spacing","title":"Type argument list spacing","text":"

Spacing before and after the angle brackets of a type argument list.

Ktlint Disallowed
val res = ArrayList<LintError>()\n\nclass B<T> : A<T>() {\n    override fun x() = super<A>.x()\n}\n
val res = ArrayList < LintError > ()\n\nclass B<T> : A< T >() {\n    override fun x() = super< A >.x()\n}\n

Rule id: standard:type-argument-list-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:type-argument-list-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_type-argument-list-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_type-argument-list-spacing = disabled\n
"},{"location":"rules/standard/#type-parameter-list-spacing","title":"Type parameter list spacing","text":"

Spacing after a type parameter list in function and class declarations.

Ktlint Disallowed
fun <T> foo1(t: T) = \"some-result\"\n\nfun <T> foo2(t: T) = \"some-result\"\n\nfun <T> foo3(t: T) = \"some-result\"\n
fun<T> foo1(t: T) = \"some-result\"\n\nfun <T>foo2(t: T) = \"some-result\"\n\nfun<T>foo3(t: T) = \"some-result\"\n

Rule id: standard:type-parameter-list-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:type-parameter-list-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_type-parameter-list-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_type-parameter-list-spacing = disabled\n
"},{"location":"rules/standard/#unary-operator-spacing","title":"Unary operator spacing","text":"

No spaces around unary operators.

Ktlint Disallowed
fun foo1(i: Int) = i++\n\nfun foo2(i: Int) = ++i\n\nfun foo3(i: Int) = ++i\n
fun foo1(i: Int) = i ++\n\nfun foo2(i: Int) = ++ i\n\nfun foo3(i: Int) = ++\n    i\n

Rule id: standard:unary-op-spacing

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:unary-op-spacing\")\n
    Enable rule via .editorconfig
    ktlint_standard_unary-op-spacing = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_unary-op-spacing = disabled\n
"},{"location":"rules/standard/#string-template","title":"String template","text":"

Consistent string templates ($v instead of ${v}, ${p.v} instead of ${p.v.toString()})

Ktlint Disallowed
val foo = \"$foo hello\"\n
val foo = \"${foo} hello\"\n

Rule id: standard:string-template

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:string-template\")\n
    Enable rule via .editorconfig
    ktlint_standard_string-template = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_string-template = disabled\n
"},{"location":"rules/standard/#string-template-indent","title":"String template indent","text":"

Enforce consistent string template indentation for multiline string templates which are post-fixed with .trimIndent(). The opening and closing \"\"\" are placed on separate lines and the indentation of the content of the template is aligned with the \"\"\".

Ktlint Disallowed
val foo =\n    \"\"\"\n    line1\n    line2\n    \"\"\".trimIndent()\n\nfun foo() {\n    // The opening \"\"\" can not be wrapped to next line as that would result in a compilation error\n    return \"\"\"\n        line1\n        line2\n        \"\"\".trimIndent()\n}\n
val foo = \"\"\"\n          line1\n          line2\n          \"\"\".trimIndent()\n\nfun foo() {\n    return \"\"\"\n        line1\n        line2\n    \"\"\".trimIndent()\n}\n

Rule id: standard:string-template-indent

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:string-template-indent\")\n
    Enable rule via .editorconfig
    ktlint_standard_string-template-indent = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_string-template-indent = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#trailing-comma-on-call-site","title":"Trailing comma on call site","text":"

Consistent removal (default) or adding of trailing commas on call site.

Ktlint Disallowed
val foo =\n    FooWrapper(\n        Foo(\n            a = 3,\n            b = 4,\n        ),\n    )\n
val foo =\n    FooWrapper(Foo(\n        a = 3,\n        b = 4,\n    ),) // it's weird to insert \",\" between unwrapped (continued) parenthesis\n
Configuration setting ktlint_official intellij_idea android_studio ij_kotlin_allow_trailing_comma_on_call_siteDefines whether a trailing comma (or no trailing comma) should be enforced on the calling site, e.g. argument-list, when-entries, lambda-arguments, indices, etc. When set, IntelliJ IDEA uses this property to allow usage of a trailing comma by discretion of the developer. KtLint however uses this setting to enforce consistent usage of the trailing comma when set. true true false

Note

Although the Kotlin coding conventions leaves it to the developer's discretion to use trailing commas on the call site, it also states that usage of trailing commas has several benefits:

KtLint values consistent formatting more than a per-situation decision, and therefore uses this setting to enforce/disallow usage of trailing comma's on the calling site.

Rule id: standard:trailing-comma-on-call-site

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:trailing-comma-on-call-site\")\n
    Enable rule via .editorconfig
    ktlint_standard_trailing-comma-on-call-site = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_trailing-comma-on-call-site = disabled\n
"},{"location":"rules/standard/#trailing-comma-on-declaration-site","title":"Trailing comma on declaration site","text":"

Consistent removal (default) or adding of trailing commas on declaration site.

Ktlint Disallowed
class FooWrapper(\n    val foo = Foo(\n        a = 3,\n        b = 4,\n    ),\n)\n
class FooWrapper(val foo = Foo(\n    a = 3,\n    b = 4,\n),) // it's weird to insert \",\" between unwrapped (continued) parenthesis\n
Configuration setting ktlint_official intellij_idea android_studio ij_kotlin_allow_trailing_commaDefines whether a trailing comma (or no trailing comma) should be enforced on the defining site, e.g. parameter-list, type-argument-list, lambda-value-parameters, enum-entries, etc. When set, IntelliJ IDEA uses this property to allow usage of a trailing comma by discretion of the developer. KtLint however uses this setting to enforce consistent usage of the trailing comma when set. true true false

Note

The Kotlin coding conventions encourages the usage of trailing commas on the declaration site, but leaves it to the developer's discretion to use trailing commas on the call site. But next to this, it also states that usage of trailing commas has several benefits:

KtLint values consistent formatting more than a per-situation decision, and therefore uses this setting to enforce/disallow usage of trailing comma's in declarations.

Rule id: standard:trailing-comma-on-declaration-site

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:trailing-comma-on-declaration-site\")\n
    Enable rule via .editorconfig
    ktlint_standard_trailing-comma-on-declaration-site = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_trailing-comma-on-declaration-site = disabled\n
"},{"location":"rules/standard/#type-argument-comment","title":"Type argument comment","text":"

Disallows comments to be placed at certain locations inside a type argument.

Ktlint Disallowed
fun Foo<\n    /* some comment */ \n    out Any\n    >.foo() {}\nfun Foo<\n    // some comment \n    out Any\n    >.foo() {}\n
fun Foo<out /* some comment */ Any>.foo() {}\nfun Foo<\n    out Any, // some comment\n    >.foo() {}\n

Note

In some projects it is an accepted practice to use EOL comments to document the parameter before the comma as is shown below:

fun Foo<\n    out Bar1, // some comment\n    out Bar2, // some other comment\n>.foo() {}\n
Although this code sample might look ok, it is semantically and programmatically unclear to which type some comment refers. From the developer perspective it might be clear that it belongs to type Bar1. From the parsers perspective, it does belong to type Bar2.

Rule id: standard:type-argument-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:type-argument-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_type-argument-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_type-argument-comment = disabled\n
"},{"location":"rules/standard/#type-parameter-comment","title":"Type parameter comment","text":"

Disallows comments to be placed at certain locations inside a type parameter.

Ktlint Disallowed
class Foo1<\n    /* some comment */ \n    out Bar\n    >\nclass Foo2<\n    // some comment \n    out Bar\n    >\n
class Foo1<in /* some comment */ Bar>\nclass Foo2<\n    in Bar, // some comment\n    >\n

Note

In some projects it is an accepted practice to use EOL comments to document the parameter before the comma as is shown below:

class Foo<\n    out Bar1, // some comment\n    out Bar2, // some other comment\n>\n

Although this code sample might look ok, it is semantically and programmatically unclear on which parameter some comment refers. From the developer perspective it might be clear that it belongs to type Bar1. From the parsers perspective, it does belong to type Bar2.

Rule id: standard:type-parameter-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:type-parameter-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_type-parameter-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_type-parameter-comment = disabled\n
"},{"location":"rules/standard/#unnecessary-parenthesis-before-trailing-lambda","title":"Unnecessary parenthesis before trailing lambda","text":"

An empty parentheses block before a lambda is redundant.

Ktlint Disallowed
val foo = \"some-string\".count { it == '-' }\n
val foo = \"some-string\".count() { it == '-' }\n

Rule id: standard:unnecessary-parentheses-before-trailing-lambda

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:unnecessary-parentheses-before-trailing-lambda\")\n
    Enable rule via .editorconfig
    ktlint_standard_unnecessary-parentheses-before-trailing-lambda = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_unnecessary-parentheses-before-trailing-lambda = disabled\n
"},{"location":"rules/standard/#value-argument-comment","title":"Value argument comment","text":"

Disallows comments to be placed at certain locations inside a value argument.

Ktlint Disallowed
val foo1 =\n    foo(\n        /* some comment */\n        bar = \"bar\"\n    )\nval foo2 =\n    foo(\n        // some comment\n        bar = \"bar\"\n    )\n
val foo1 = foo(bar /* some comment */ = \"bar\")\nval foo2 = \n    foo(\n        bar = // some comment\n            \"bar\"\n    )\n

Rule id: standard:value-argument-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:value-argument-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_value-argument-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_value-argument-comment = disabled\n
"},{"location":"rules/standard/#value-parameter-comment","title":"Value parameter comment","text":"

Disallows comments to be placed at certain locations inside a value argument.

Ktlint Disallowed
class Foo1(\n    /** some kdoc */\n    bar = \"bar\"\n)\nclass Foo2(\n    /* some comment */\n    bar = \"bar\"\n)\nclass Foo3(\n    // some comment\n    bar = \"bar\"\n)\n
class Foo1(\n   bar = /** some kdoc */ \"bar\"\n)\nclass Foo2(\n   bar = /* some comment */ \"bar\"\n)\nclass Foo3(\n    bar =\n       // some comment\n       \"bar\"\n)\n

Rule id: standard:value-parameter-comment

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:value-parameter-comment\")\n
    Enable rule via .editorconfig
    ktlint_standard_value-parameter-comment = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_value-parameter-comment = disabled\n
"},{"location":"rules/standard/#wrapping","title":"Wrapping","text":""},{"location":"rules/standard/#argument-list-wrapping","title":"Argument list wrapping","text":"

All arguments should be on the same line, or every argument should be on a separate line.

Ktlint Disallowed
val foo =\n    foo(\n        a,\n        b,\n        c,\n    )\n
val foo =\n    foo(\n        a,\n        b, c,\n    )\n
Configuration setting ktlint_official intellij_idea android_studio ktlint_argument_list_wrapping_ignore_when_parameter_count_greater_or_equal_than unset 8 8 max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:argument-list-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:argument-list-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_argument-list-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_argument-list-wrapping = disabled\n
"},{"location":"rules/standard/#chain-wrapping","title":"Chain wrapping","text":"

When wrapping chained calls ., ?. and ?: should be placed on the next line

Ktlint Disallowed
val foo =\n    listOf(1, 2, 3)\n        .filter { it > 2 }!!\n        .takeIf { it.count() > 100 }\n        ?.sum()\nval foobar =\n    foo()\n        ?: bar\n
val foo =\n    listOf(1, 2, 3).\n        filter { it > 2 }!!.\n        takeIf { it.count() > 100 }?.\n        sum()\nval foobar =\n    foo() ?:\n        bar\n

Rule id: standard:chain-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:chain-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_chain-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_chain-wrapping = disabled\n
"},{"location":"rules/standard/#comment-wrapping","title":"Comment wrapping","text":"

A block comment should start and end on a line that does not contain any other element.

Ktlint Disallowed
// Some comment 1\nval foo1 = \"foo1\"\nval foo2 = \"foo\" // Some comment\nval foo3 = { /* no-op */ } \n
/* Some comment 1 */ val foo1 = \"foo1\"\nval foo2 = \"foo\" /* Block comment instead of end-of-line comment */\nval foo3 = \"foo\" /* Some comment\n                  * with a newline\n                  */\n

Rule id: standard:comment-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:comment-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_comment-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_comment-wrapping = disabled\n
"},{"location":"rules/standard/#condition-wrapping","title":"Condition wrapping","text":"

Wraps each operand in a multiline condition to a separate line.

Ktlint Disallowed
val foo = bar || baz\nif (bar1 ||\n    bar2 ||\n    baz1 ||\n    (baz2 && baz3)\n) {\n   // do something\n}\n
val foo =\n  multiLineOperand(\n      \"bar\"\n  ) || baz\nif (bar1 || bar2 ||\n    baz1 || (baz2 && baz3)\n) {\n   // do something\n}\n

Rule id: standard:condition-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:condition-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_condition-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_condition-wrapping = disabled\n
"},{"location":"rules/standard/#content-receiver-wrapping","title":"Content receiver wrapping","text":"

Wraps the content receiver list to a separate line regardless of maximum line length. If the maximum line length is configured and is exceeded, wrap the context receivers and if needed its projection types to separate lines.

Ktlint Disallowed
// Always wrap regardless of whether max line length is set\ncontext(Foo)\nfun fooBar()\n\n// Wrap each context receiver to a separate line when the\n// entire context receiver list does not fit on a single line\ncontext(\n    Fooooooooooooooooooo1,\n    Foooooooooooooooooooooooooooooo2\n)\nfun fooBar()\n\n// Wrap each context receiver to a separate line when the\n// entire context receiver list does not fit on a single line.\n// Also, wrap each of it projection types in case a context\n// receiver does not fit on a single line after it has been\n// wrapped.\ncontext(\n    Foooooooooooooooo<\n        Foo,\n        Bar,\n        >\n)\nfun fooBar()\n
// Should be wrapped regardless of whether max line length is set\ncontext(Foo) fun fooBar()\n\n// Should be wrapped when the entire context receiver list does not\n// fit on a single line\ncontext(Fooooooooooooooooooo1, Foooooooooooooooooooooooooooooo2)\nfun fooBar()\n\n// Should be wrapped when the entire context receiver list does not\n// fit on a single line. Also, it should wrap each of it projection\n// type in case a context receiver does not fit on a single line \n// after it has been wrapped.\ncontext(Foooooooooooooooo<Foo, Bar>)\nfun fooBar()\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:context-receiver-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:context-receiver-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_context-receiver-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_context-receiver-wrapping = disabled\n
"},{"location":"rules/standard/#enum-wrapping","title":"Enum wrapping","text":"

An enum should be a single line, or each enum entry has to be placed on a separate line. In case the enumeration contains enum entries and declarations those are to be separated by a blank line.

Ktlint Disallowed
enum class Foo { A, B, C, D }\n\nenum class Foo {\n    A,\n    B,\n    C,\n    D,\n    ;\n\n    fun foo() = \"foo\"\n}\n
enum class Foo {\n    A,\n    B, C,\n    D\n}\n\nenum class Foo {\n    A;\n    fun foo() = \"foo\"\n}\n

Rule id: standard:enum-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:enum-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_enum-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_enum-wrapping = disabled\n
"},{"location":"rules/standard/#if-else-wrapping","title":"If else wrapping","text":"

A single line if-statement should be kept simple. It may contain no more than one else-branch. The branches may not be wrapped in a block.

Ktlint Disallowed
fun foobar() {\n    if (true) foo()\n    if (true) foo() else bar()\n}\n
fun foobar() {\n    if (true) if (false) foo() else bar()\n    if (true) bar() else if (false) foo() else bar()\n    if (true) { foo() } else bar()\n    if (true) bar() else { if (false) foo() else bar() }\n}\n

Rule id: standard:if-else-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:if-else-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_if-else-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_if-else-wrapping = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#multiline-expression-wrapping","title":"Multiline expression wrapping","text":"

Multiline expression on the right hand side of an expression are forced to start on a separate line. Expressions in return statement are excluded as that would result in a compilation error.

Setting ktlint_function_signature_body_expression_wrapping of the function-signature rule takes precedence when set to default. This setting keeps the first line of a multiline expression body on the same line as the end of function signature as long as the max line length is not exceeded. In that case, this rule does not wrap the multiline expression.

Ktlint Disallowed
val foo =\n    foo(\n        parameterName =\n            \"The quick brown fox \"\n                .plus(\"jumps \")\n                .plus(\"over the lazy dog\"),\n    )\n
val foo = foo(\n    parameterName = \"The quick brown fox \"\n        .plus(\"jumps \")\n        .plus(\"over the lazy dog\"),\n)\n

Rule id: standard:multiline-expression-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:multiline-expression-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_multiline-expression-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_multiline-expression-wrapping = disabled\n

Note

This rule is only run when ktlint_code_style is set to ktlint_official or when the rule is enabled explicitly.

"},{"location":"rules/standard/#parameter-list-wrapping","title":"Parameter list wrapping","text":"

When class/function signature doesn't fit on a single line, each parameter must be on a separate line.

Note

Wrapping of parameters is also influenced by the function-signature rule.

Ktlint Disallowed (ktlint_official) Disallowed (non ktlint_official)\"
// If `ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than` equals\n// `unset` the parameters are not wrapped as long as they fit on a single line\nclass ClassA(paramA: String, paramB: String, paramC: String)\n\nclass ClassA(\n    paramA: String,\n    paramB: String,\n    paramC: String\n)\n\n// If `ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than` equals\n// `unset` the parameters are not wrapped as long as they fit on a single line\nfun f(a: Any, b: Any, c: Any)\n\nfun f(\n    a: Any,\n    b: Any,\n    c: Any\n)\n\nfun foo(\n    @Bar fooBar: FooBar\n)\n
class ClassA(\n    paramA: String, paramB: String,\n    paramC: String\n)\n\nfun f(\n    a: Any,\n    b: Any, c: Any\n)\n\nfun foo(@Bar fooBar: FooBar)\n
class ClassA(\n    paramA: String, paramB: String,\n    paramC: String\n)\n\nfun f(\n    a: Any,\n    b: Any, c: Any\n)\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:parameter-list-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:parameter-list-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_parameter-list-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_parameter-list-wrapping = disabled\n
"},{"location":"rules/standard/#parameter-wrapping","title":"Parameter wrapping","text":"

When a function or class parameter doesn't fit on a single line, wrap the type or value to a separate line

Ktlint (ktlint_official) Ktlint (non ktlint_official) Disallowed
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Bar(\n    val fooooooooooooooooooooooooTooLong:\n        Foo,\n)\n\nfun bar(\n    fooooooooooooooooooooooooTooLong:\n        Foo,\n)\n
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Bar(\n    val fooooooooooooooooooooooooTooLong:\n    Foo,\n)\n\nfun bar(\n    fooooooooooooooooooooooooTooLong:\n    Foo,\n)\n
// Assume that the last allowed character is\n// at the X character on the right           X\nclass Bar(\n    val fooooooooooooooooooooooooTooLong: Foo,\n)\n\nfun bar(\n    fooooooooooooooooooooooooooooTooLong: Foo,\n)\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:parameter-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:parameter-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_parameter-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_parameter-wrapping = disabled\n
"},{"location":"rules/standard/#property-wrapping","title":"Property wrapping","text":"

When a property doesn't fit on a single line, wrap the type or value to a separate line

Ktlint Disallowed
// Assume that the last allowed character is\n// at the X character on the right           X\nval aVariableWithALooooooooooooongName:\n    String\n
// Assume that the last allowed character is\n// at the X character on the right           X\nval aVariableWithALooooooooooooongName: String\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:property-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:property-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_property-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_property-wrapping = disabled\n
"},{"location":"rules/standard/#statement-wrapping","title":"Statement wrapping","text":"

A function, class/object body or other block body statement has to be placed on different line than the braces of the body block.

Ktlint Disallowed
fun foo() {\n    if (true) {\n        // do something\n    }\n}\n\nclass A {\n    val a = 0\n    val b = 1\n}\n\nenum class FooBar1 { FOO, BAR }\n\nenum class FooBar2 {\n    FOO,\n    BAR,\n}\n
fun foo() { if (true) {\n        // do something\n    }\n}\n\nclass A { val a = 0\n    val b = 1 }\n

Rule id: standard:statement-wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:statement-wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_statement-wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_statement-wrapping = disabled\n
"},{"location":"rules/standard/#wrapping_1","title":"Wrapping","text":"

Inserts missing newlines (for example between parentheses of a multi-line function call).

Ktlint Disallowed
val foo =\n    foo(\n        a,\n        b,\n        c,\n    )\n
val foo = foo(\n    a,\n    b,\n    c)\n
Configuration setting ktlint_official intellij_idea android_studio max_line_lengthMaximum length of a (regular) line. This property is ignored in case the max-line-length rule is disabled, or when using Ktlint via a third party integration that does not provide this rule. 140 off 100

Rule id: standard:wrapping

Suppress or disable rule (1)

  1. Suppress rule in code with annotation below:
    @Suppress(\"ktlint:standard:wrapping\")\n
    Enable rule via .editorconfig
    ktlint_standard_wrapping = enabled\n
    Disable rule via .editorconfig
    ktlint_standard_wrapping = disabled\n
"}]} \ No newline at end of file