An anti-bikeshedding Kotlin linter with built-in formatter

Related tags

App kotlin lint linter
Overview

Join the chat at https://kotlinlang.slack.com Build status Maven Central ktlint

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

Features

  • No configuration.* Which means no decisions to make, nothing to argue about and no special files to manage.
    While this might sound extreme, keep in mind that ktlint tries to capture (reflect) official code style* from kotlinlang.org and Android Kotlin Style Guide (+ we respect your .editorconfig and support additional ruleset|s).
  • Built-in formatter. So that you wouldn't have to fix all style violations by hand.
  • Customizable output. plain (+ plain?group_by_file), json, html and checkstyle reporters are available out-of-the-box. It's also easy to create your own.
  • A single executable jar with all dependencies included.

Installation | Usage | Integration with Maven / Gradle / IntelliJ IDEA / Emacs / Continuous Integration | Creating a ruleset | a reporter | Badge | FAQ

Standard rules

  • Indentation formatting - respects .editorconfig indent_size with no continuation indent (see EditorConfig section for more) (id: indent)
  • No semicolons (unless used to separate multiple statements on the same line) (id: no-semi)
  • No unused imports (id: no-unused-imports)
  • No consecutive blank lines (id: no-consecutive-blank-lines)
  • No blank lines before } (id: no-blank-line-before-rbrace)
  • No trailing whitespaces (id: no-trailing-spaces)
  • No Unit returns (fun fn {} instead of fun fn: Unit {}) (id: no-unit-return)
  • No empty ({}) class bodies (id: no-empty-class-body)
  • No wildcard imports (id: no-wildcard-imports)
  • When wrapping chained calls ., ?. and ?: should be placed on the next line (id: chain-wrapping)
  • When a line is broken at an assignment (=) operator the break comes after the symbol (id: no-line-break-before-assignment)
  • When class/function signature doesn't fit on a single line, each parameter must be on a separate line
  • Consistent string templates ($v instead of ${v}, ${p.v} instead of ${p.v.toString()}) (id: string-template)
  • Consistent order of modifiers (id: modifier-order)
  • Consistent spacing after keywords, commas; around colons, curly braces, parens, infix operators, comments, range operators, etc (ids: colon-spacing, comma-spacing, curly-spacing, dot-spacing, double-colon-spacing, keyword-spacing, op-spacing, paren-spacing, range-spacing)
  • Newline at the end of each file (enabled by default) (set insert_final_newline=false in .editorconfig to disable (see EditorConfig section for more)). (id: final-newline)
  • Imports ordered consistently (see Custom ktlint EditorConfig properties for more) (id: import-ordering)

Experimental rules

New rules will be added into the experimental ruleset, which can be enabled by passing the --experimental flag to ktlint.

  • Annotation formatting - 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 (id: experimental:annotation)
  • Annotations should be separated by the annotated declaration by a single line break (id: experimental:annotation-spacing)
  • Argument list wrapping (id: experimental:argument-list-wrapping)
  • Enum entry names should be uppercase underscore-separated names (id: experimental:enum-entry-name-case)
  • Braces required for multiline if/else statements (id: experimental:multiline-if-else)
  • No leading empty lines in method blocks (id: experimental:no-empty-first-line-in-method-block)
  • No underscores in package names (id: experimental:package-name)
  • No spaces around angle brackets (id: experimental:spacing-around-angle-brackets)
  • No spaces around :: (id: experimental:double-colon-spacing)
  • No spaces around unary operators (id: experimental:unary-op-spacing)
  • Declarations with annotations should be separated by a blank line (id: experimental:spacing-between-declarations-with-annotations)
  • Declarations with comments should be separated by a blank line (id: experimental:spacing-between-declarations-with-comments)

EditorConfig

ktlint recognizes the following .editorconfig properties (provided they are specified under [*.{kt,kts}]):
(values shown below are the defaults and do not need to be specified explicitly)

[*.{kt,kts}]
# possible values: number (e.g. 2), "unset" (makes ktlint ignore indentation completely)  
indent_size=4
# true (recommended) / false
insert_final_newline=true
# possible values: number (e.g. 120) (package name, imports & comments are ignored), "off"
# it's automatically set to 100 on `ktlint --android ...` (per Android Kotlin Style Guide)
max_line_length=off

IntelliJ IDEA .editorconfig autoformat issue

Unfortunately IntelliJ IDEA has .editorconfig autoformat issue that adds additional space into glob statements. For example, [*{kt,kts}] is formatted into [*{kt, kts}] (original ktlint issue). Such behaviour violates .editorconfig specification and leads to ignoring this section when ktlint is parsing it.

Custom Ktlint specific EditorConfig properties

# Comma-separated list of rules to disable (Since 0.34.0)
# Note that rules in any ruleset other than the standard ruleset will need to be prefixed 
# by the ruleset identifier.
disabled_rules=no-wildcard-imports,experimental:annotation,my-custom-ruleset:my-custom-rule

# Defines the imports layout. The layout can be composed by the following symbols:
# "*" - wildcard. There must be at least one entry of a single wildcard to match all other imports. Matches anything after a specified symbol/import as well.
# "|" - blank line. Supports only single blank lines between imports. No blank line is allowed in the beginning or end of the layout.
# "^" - alias import, e.g. "^android.*" will match all android alias imports, "^" will match all other alias imports.
# import paths - these can be full paths, e.g. "java.util.List.*" as well as wildcard paths, e.g. "kotlin.**"
# Examples (we use ij_kotlin_imports_layout to set an imports layout for both ktlint and IDEA via a single property):
ij_kotlin_imports_layout=* # alphabetical with capital letters before lower case letters (e.g. Z before a), no blank lines
ij_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
ij_kotlin_imports_layout=android.**,|,^org.junit.**,kotlin.io.Closeable.*,|,*,^ # custom imports layout

# According to https://kotlinlang.org/docs/reference/coding-conventions.html#names-for-test-methods it is acceptable to write method names
# in natural language. When using natural language, the description tends to be longer. Allow lines containing an identifier between
# backticks to be longer than the maximum line length. (Since 0.41.0)
[**/test/**.kt]
ktlint_ignore_back_ticked_identifier=true

Overriding Editorconfig properties for specific directories

You could override properties for specific directories inside your project:

[*.{kt,kts}]
disabled_rules=import-ordering

# Note that in this case 'import-ordering' rule will be active and 'indent' will be disabled
[api/*.{kt,kts}]
disabled_rules=indent

Online demo

You can try ktlint online here using the standard or a custom ruleset without installing it to your PC.
To contribute or get more info, please visit the GitHub repository.

Installation

Skip all the way to the "Integration" section if you don't plan to use ktlint's command line interface.

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

... or just download ktlint from the releases page

  • ktlint.asc contains PGP signature which you can verify with:
    • (Releases up through 0.31.0) curl -sS https://keybase.io/shyiko/pgp_keys.asc | gpg --import && gpg --verify ktlint.asc
    • (Releases from 0.32.0 on) curl -sS https://keybase.io/ktlint/pgp_keys.asc | gpg --import && gpg --verify ktlint.asc

On macOS (or Linux) you can also use brew - brew install ktlint - or MacPorts - port install ktlint. On Arch Linux, you can install ktlint AUR.

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 ... is enough.

Command line usage

# Get help about all available commands
$ ktlint --help

# Check the style of all Kotlin files (ending with '.kt' or '.kts') inside the current dir (recursively).
# Hidden folders will be skipped.
$ ktlint
  
# Check only certain locations starting from the current directory.
#
# Prepend ! to negate the pattern, KtLint uses .gitignore pattern style syntax.
# Globs are applied starting from the last one.
#
# Hidden folders will be skipped.
# Check all '.kt' files in 'src/' directory, but ignore files ending with 'Test.kt':
ktlint "src/**/*.kt" "!src/**/*Test.kt"
# Check all '.kt' files in 'src/' directory, but ignore 'generated' directory and its subdirectories:
ktlint "src/**/*.kt" "!src/**/generated/**"

# Auto-correct style violations.
# If some errors cannot be fixed automatically they will be printed to stderr. 
$ ktlint -F "src/**/*.kt"

# Print style violations grouped by file.
$ ktlint --reporter=plain?group_by_file

# Print style violations as usual + create report in checkstyle format, specifying report location. 
$ ktlint --reporter=plain --reporter=checkstyle,output=ktlint-report-in-checkstyle-format.xml

# Check against a baseline file.
$ ktlint --baseline=ktlint-baseline.xml

# Install git hook to automatically check files for style violations on commit.
# Run "ktlint installGitPrePushHook" if you wish to run ktlint on push instead.
$ ktlint installGitPreCommitHook

on Windows you'll have to use java -jar ktlint ....

ktlint --help for more.

Integration

... with Maven

pom.xml

...
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.8</version>
    <executions>
        <execution>
            <id>ktlint</id>
            <phase>verify</phase>
            <configuration>
            <target name="ktlint">
                <java taskname="ktlint" dir="${basedir}" fork="true" failonerror="true"
                    classpathref="maven.plugin.classpath" classname="com.pinterest.ktlint.Main">
                    <arg value="src/**/*.kt"/>
                    <!-- to generate report in checkstyle format prepend following args: -->
                    <!-- 
                    <arg value="--reporter=plain"/>
                    <arg value="--reporter=checkstyle,output=${project.build.directory}/ktlint.xml"/>
                    -->
                    <!-- see https://github.com/pinterest/ktlint#usage for more -->                    
                </java>
            </target>
            </configuration>
            <goals><goal>run</goal></goals>
        </execution>
        <execution>
            <id>ktlint-format</id>
            <configuration>
            <target name="ktlint">
                <java taskname="ktlint" dir="${basedir}" fork="true" failonerror="true"
                    classpathref="maven.plugin.classpath" classname="com.pinterest.ktlint.Main">
                    <arg value="-F"/>
                    <arg value="src/**/*.kt"/>
                </java>
            </target>
            </configuration>
            <goals><goal>run</goal></goals>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>com.pinterest</groupId>
            <artifactId>ktlint</artifactId>
            <version>0.43.2</version>
        </dependency>
        <!-- additional 3rd party ruleset(s) can be specified here -->
    </dependencies>
</plugin>
...

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).

To check code style - mvn antrun:run@ktlint (it's also bound to mvn verify).
To run formatter - mvn antrun:run@ktlint-format.

Another option is to use a dedicated Maven plugin - gantsign/ktlint-maven-plugin.

... with Gradle

(with a plugin - Recommended)

Gradle plugins (in order of appearance):

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

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

You might also want to take a look at diffplug/spotless or autostyle/autostyle that have a built-in support for ktlint. In addition to linting/formatting kotlin code it allows you to keep license headers, markdown documentation, etc. in check.

(without a plugin)

build.gradle

// kotlin-gradle-plugin must be applied for configuration below to work
// (see https://kotlinlang.org/docs/reference/using-gradle.html)

apply plugin: 'java'

repositories {
    mavenCentral()
}

configurations {
    ktlint
}

dependencies {
    ktlint("com.pinterest:ktlint:0.43.2") {
        attributes {
            attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))
        }
    }
    // additional 3rd party ruleset(s) can be specified here
    // just add them to the classpath (e.g. ktlint 'groupId:artifactId:version') and 
    // ktlint will pick them up
}

task ktlint(type: JavaExec, group: "verification") {
    description = "Check Kotlin code style."
    classpath = configurations.ktlint
    main = "com.pinterest.ktlint.Main"
    args "src/**/*.kt"
    // to generate report in checkstyle format prepend following args:
    // "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/ktlint.xml"
    // to add a baseline to check against prepend following args:
    // "--baseline=ktlint-baseline.xml"
    // see https://github.com/pinterest/ktlint#usage for more
}
check.dependsOn ktlint

task ktlintFormat(type: JavaExec, group: "formatting") {
    description = "Fix Kotlin code style deviations."
    classpath = configurations.ktlint
    main = "com.pinterest.ktlint.Main"
    args "-F", "src/**/*.kt"
}

To check code style - gradle ktlint (it's also bound to gradle check).
To run formatter - gradle ktlintFormat.

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

(without a plugin) for Gradle Kotlin DSL (build.gradle.kts)

build.gradle.kts

val ktlint by configurations.creating

dependencies {
    ktlint("com.pinterest:ktlint:0.43.2") {
        attributes {
            attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.EXTERNAL))
        }
    }
    // ktlint(project(":custom-ktlint-ruleset")) // in case of custom ruleset
}

val outputDir = "${project.buildDir}/reports/ktlint/"
val inputFiles = project.fileTree(mapOf("dir" to "src", "include" to "**/*.kt"))

val ktlintCheck by tasks.creating(JavaExec::class) {
    inputs.files(inputFiles)
    outputs.dir(outputDir)

    description = "Check Kotlin code style."
    classpath = ktlint
    main = "com.pinterest.ktlint.Main"
    args = listOf("src/**/*.kt")
}

val ktlintFormat by tasks.creating(JavaExec::class) {
    inputs.files(inputFiles)
    outputs.dir(outputDir)

    description = "Fix Kotlin code style deviations."
    classpath = ktlint
    main = "com.pinterest.ktlint.Main"
    args = listOf("-F", "src/**/*.kt")
}

... with IntelliJ IDEA

While this is not strictly necessary it makes Intellij IDEA's built-in formatter produce 100% ktlint-compatible code.

Option #1 (recommended)

To change the code style config files in a single IDEA project

Run ktlint executable with the appropriate flag:

(inside project's root directory)

ktlint applyToIDEAProject
# or if you want to be compliant with Android Kotlin Style Guide
ktlint --android applyToIDEAProject
Option #2

To change the code style config files for all IDEA projects

Run ktlint executable with the appropriate flag:

ktlint applyToIDEA

Or if you want to use android specific code style:

ktlint --android applyToIDEA
Option #3

Go to File -> Settings... -> Editor

  • General -> Auto Import
    • check Kotlin / Optimize imports on the fly (for current project).
  • Code Style -> Kotlin
    • Set from... on the right -> (Predefined style) -> Kotlin style guide (Kotlin plugin 1.2.20+).
    • open Code Generation tab
      • uncheck Line comment at first column;
      • select Add a space at comment start.
    • open Imports tab
      • select Use single name import (all of them);
      • remove import java.util.* from Packages to Use Import with '*'.
    • open Blank Lines tab
      • change Keep Maximum Blank Lines / In declarations & In code to 1 and Before '}' to 0.
    • (optional but recommended) open Wrapping and Braces tab
      • uncheck Function declaration parameters (OR Methods declartion parameters for older version) / Align when multiline.
    • (optional but recommended) open Tabs and Indents tab
      • change Continuation indent to the same value as Indent (4 by default).
  • Inspections
    • change Severity level of Unused import directive and Redundant semicolon under Kotlin -> Redundant constructs to ERROR.

... with GNU Emacs

See whirm/flycheck-kotlin.

... with Vim

See w0rp/ale.

Integrated with something else? Send a PR.

... with Continuous Integration

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

Creating a ruleset

See also Writing your first ktlint rule by Niklas Baudy.

In a nutshell: "ruleset" is a JAR containing one or more Rules gathered together in a RuleSet. ktlint is relying on 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/com.pinterest.ktlint.core.RuleSetProvider file containing a fully qualified name of your RuleSetProvider implementation).

Once packaged in a JAR e.g. via ./gradlew build you can load it with

# enable additional 3rd party ruleset by pointing ktlint to its location on the file system
$ ktlint -R /path/to/custom/rulseset.jar "src/test/**/*.kt"

Loading custom (3rd party) ruleset via built-in maven dependency resolver is deprecated, see https://github.com/pinterest/ktlint/issues/451.

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).

AST

While writing/debugging Rules it's often helpful to have an AST printed out to see the structure rules have to work with. ktlint >= 0.15.0 has a printAST subcommand (or --print-ast flag for ktlint < 0.34.0) specifically for this purpose (usage: ktlint --color printAST <file>). An example of the output is shown below.

$ printf "fun main() {}" | ktlint --color printAST --stdin

1: ~.psi.KtFile (~.psi.stubs.elements.KtFileElementType.kotlin.FILE)
1:   ~.psi.KtPackageDirective (~.psi.stubs.elements.KtPlaceHolderStubElementType.PACKAGE_DIRECTIVE) ""
1:   ~.psi.KtImportList (~.psi.stubs.elements.KtPlaceHolderStubElementType.IMPORT_LIST) ""
1:   ~.psi.KtScript (~.psi.stubs.elements.KtScriptElementType.SCRIPT)
1:     ~.psi.KtBlockExpression (~.KtNodeType.BLOCK)
1:       ~.psi.KtNamedFunction (~.psi.stubs.elements.KtFunctionElementType.FUN)
1:         ~.c.i.p.impl.source.tree.LeafPsiElement (~.lexer.KtKeywordToken.fun) "fun"
1:         ~.c.i.p.impl.source.tree.PsiWhiteSpaceImpl (~.c.i.p.tree.IElementType.WHITE_SPACE) " "
1:         ~.c.i.p.impl.source.tree.LeafPsiElement (~.lexer.KtToken.IDENTIFIER) "main"
1:         ~.psi.KtParameterList 
  (~.psi.stubs.elements.KtPlaceHolderStubElementType.VALUE_PARAMETER_LIST)
1:           ~.c.i.p.impl.source.tree.LeafPsiElement (~.lexer.KtSingleValueToken.LPAR) "("
1:           ~.c.i.p.impl.source.tree.LeafPsiElement (~.lexer.KtSingleValueToken.RPAR) ")"
1:         ~.c.i.p.impl.source.tree.PsiWhiteSpaceImpl (~.c.i.p.tree.IElementType.WHITE_SPACE) " "
1:         ~.psi.KtBlockExpression (~.KtNodeType.BLOCK)
1:           ~.c.i.p.impl.source.tree.LeafPsiElement (~.lexer.KtSingleValueToken.LBRACE) "{"
1:           ~.c.i.p.impl.source.tree.LeafPsiElement (~.lexer.KtSingleValueToken.RBRACE) "}"

   format: <line_number:> <node.psi::class> (<node.elementType>) "<node.text>"
   legend: ~ = org.jetbrains.kotlin, c.i.p = com.intellij.psi
   

Creating a reporter

Take a look at ktlint-reporter-plain.

In short, all you need to do is to implement a Reporter and make it available by registering a custom ReporterProvider using META-INF/services/com.pinterest.ktlint.core.ReporterProvider. 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).

Loading custom (3rd party) reporter via built-in maven dependency resolver is deprecated, see https://github.com/pinterest/ktlint/issues/451.

Third-party:

Badge

ktlint

[![ktlint](https://img.shields.io/badge/code%20style-%E2%9D%A4-FF4081.svg)](https://ktlint.github.io/)

FAQ

Why should I use ktlint?

Simplicity.

Spending time on configuration (& 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 & 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).

Can I have my own rules on top of ktlint?

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 Creating A Ruleset.

How do I suppress an error for a line/block/file?

This 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 to turn on the verbose mode (ktlint --verbose ...). At the end of each line you'll see an error code. Use it as an argument for ktlint-disable directive (shown below).

import package.* // ktlint-disable no-wildcard-imports

/* ktlint-disable no-wildcard-imports */
import package.a.*
import package.b.*
/* ktlint-enable no-wildcard-imports */

To disable all checks:

import package.* // ktlint-disable

How do I globally disable a rule?

See the EditorConfig section for details on how to use the disabled_rules property.

You may also pass a list of disabled rules via the --disabled_rules command line flag. It has the same syntax as the EditorConfig property.

Development

Make sure to read CONTRIBUTING.md.

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

To open ktlint in Intellij IDEA:
File -> Open... (you may need to right-click on pom.xml (in the project dir) and then Maven -> Reimport).
You'll also need to set "Project SDK" to 1.8, "Project language level" to 8 in "Project Settings" (File -> Project Structure...).
To run ktlint - right-click on ktlint/src/main/kotlin/com/pinterest/ktlint/Main.kt -> Run.

Access to the latest master snapshot

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:

Maven
...
<repository>
    <id>sonatype-snapshots</id>
    <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    <snapshots>
        <enabled>true</enabled>
    </snapshots>
    <releases>
        <enabled>false</enabled>
    </releases>
</repository>
...
Gradle
repositories {
  maven {
    url "https://oss.sonatype.org/content/repositories/snapshots"
  }
}
Kotlin development version snapshot

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

Legal

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

Comments
  • Wildcard imports

    Wildcard imports

    Please forgive my bikeshedding, but I beg to differ with the "no wildcards" rule. My primary argument is that intellij does add wildcard imports in the default configuration, and I think I should not have to configure intellij to play nice with ktlint. Adding // ktlint-disable no-wildcard-imports is a very ugly workaround.

    Another acceptable solution for me would be if the format action actually resolved wildcard imports into individual imports, which it does not as of version 0.7.0. I don't want to argue about what's better, I just want to have a consistent style without requiring manual intervention.

    opened by fwilhe 57
  • Alphabetical import ordering enabled by default is a problem in Android Studio/IntelliJ

    Alphabetical import ordering enabled by default is a problem in Android Studio/IntelliJ

    In our project ktlint 0.34.0 now reports a lot of incorrect import ordering, although we use a default import layou of IDE. All our developers have "Optimize imports" enabled by default, but this still creates an order like the following (which seems to be default one of Kotlin IDE plugin):

    import ru.example.a
    import ru.example.b
    import ru.example.c
    import javax.inject.Inject
    

    Notice that the last one comes in non alphabetical order. The unfortunate thing is that this cannot be changed.

    Import order editing is there only for Java CodeStyle, kotlin plugin seems not to provide it. Correct me if I'm wrong.

    If you think that this is still something that should be default, then please close.

    But currently I suspect that many Android Studio/IntelliJ users will be disabling this rule, otherwise they'll have an endless conflict between IDE autoformatter/ktlint.

    opened by dimsuz 50
  • Rule to mandate/forbid trailing commas

    Rule to mandate/forbid trailing commas

    Expected Behavior

    ktlint offers a rule that enforces a particular code style regarding trailing commas, which are now permitted by the Kotlin compiler as of 1.3.70, see https://youtrack.jetbrains.com/issue/KT-34743 for more details.

    This may not be a good fit for ktlint as it's too opinionated and no conventions exist yet, but if it's suitable it's a better fit here than in detekt where it was originally proposed.

    Observed Behavior

    No such rule exists.

    Steps to Reproduce

    N/A, new rule required.

    Your Environment

    • Version of ktlint used:
    • Name and version (or code for custom task) of integration used (Gradle plugin, Maven plugin, command line, custom Gradle task):
    • Version of Gradle used (if applicable):
    • Operating System and version:
    • Link to your project (if it's a public repository):
    new rule 
    opened by 3flex 41
  • Process of migrating to gradle - Add maven publish

    Process of migrating to gradle - Add maven publish

    @shashachu

    Add support for publish Ktlint via Gradle I used @vanniktech's plugin and here is an example of integrating it: https://github.com/square/okhttp/commit/c53f8db73d53eb8fc1c5d426568d35e9b99c2fa2.

    opened by jaredsburrows 31
  • ktlint fails on Java 16+

    ktlint fails on Java 16+

    Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Could not initialize class org.jetbrains.kotlin.com.intellij.pom.java.LanguageLevel
            at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122
            at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
            at com.pinterest.ktlint.KtlintCommandLine.parallel(Main.kt:575)
            at com.pinterest.ktlint.KtlintCommandLine.parallel$default(Main.kt:547)
            at com.pinterest.ktlint.KtlintCommandLine.lintFiles(Main.kt:298)
            at com.pinterest.ktlint.KtlintCommandLine.run(Main.kt:262)
            at com.pinterest.ktlint.Main.main(Main.kt:70)
    Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.jetbrains.kotlin.com.intellij.pom.java.LanguageLevel
            at org.jetbrains.kotlin.com.intellij.core.CoreLanguageLevelProjectExtension.<init>(CoreLanguageLevelProjectExtension.java:26)
            at org.jetbrains.kotlin.com.intellij.core.JavaCoreProjectEnvironment.<init>(JavaCoreProjectEnvironment.java:42)
            at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment.<init>(KotlinCoreProjectEnvironment.kt:26)
            at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$ProjectEnvironment.<init>(KotlinCoreEnvironment.kt:121)
            at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:425)
            at com.pinterest.ktlint.core.internal.KotlinPsiFileFactory.initializePsiFileFactory(KotlinPsiFileFactory.kt:74)
            at com.pinterest.ktlint.core.internal.KotlinPsiFileFactory.acquirePsiFileFactory$ktlint_core(KotlinPsiFileFactory.kt:39)
            at com.pinterest.ktlint.core.KtLint.format(KtLint.kt:378)
            at com.pinterest.ktlint.internal.FileUtilsKt.formatFile(FileUtils.kt:182)
            at com.pinterest.ktlint.KtlintCommandLine.process(Main.kt:366)
            at com.pinterest.ktlint.KtlintCommandLine.access$process(Main.kt:89)
            at com.pinterest.ktlint.KtlintCommandLine$lintFiles$3$1.call(Main.kt:289)
            at com.pinterest.ktlint.KtlintCommandLine$lintFiles$3$1.call(Main.kt:288)
            at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
            at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
            at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
            at java.base/java.lang.Thread.run(Thread.java:831)
    
    java16+ 
    opened by itsandreramon 26
  • java.lang.reflect.InaccessibleObjectException: Unable to make field private transient java.lang.Object java.lang.Throwable.backtrace accessible: module java.base does not

    java.lang.reflect.InaccessibleObjectException: Unable to make field private transient java.lang.Object java.lang.Throwable.backtrace accessible: module java.base does not "opens java.lang" to unnamed module @76628072

    Expected Behavior

    The task should tell me if there is a problem with the code style or not.

    Observed Behavior

    Crash:

    > Task :ktlintFormat FAILED
    17:02:10.989 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with "baseline" id.
    17:02:10.989 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with "checkstyle" id.
    17:02:10.990 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with "json" id.
    17:02:10.990 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with "html" id.
    17:02:10.990 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with "plain" id.
    17:02:10.990 [main] DEBUG com.pinterest.ktlint.Main - Discovered reporter with "sarif" id.
    17:02:10.990 [main] DEBUG com.pinterest.ktlint.Main - Initializing "plain" reporter with {verbose=false, color=false, color_name=DARK_GRAY}
    Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ExceptionInInitializerError
            at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
            at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
            at com.pinterest.ktlint.KtlintCommandLine.parallel(Main.kt:606)
            at com.pinterest.ktlint.KtlintCommandLine.parallel$default(Main.kt:578)
            at com.pinterest.ktlint.KtlintCommandLine.lintFiles(Main.kt:321)
            at com.pinterest.ktlint.KtlintCommandLine.run(Main.kt:282)
            at com.pinterest.ktlint.Main.main(Main.kt:76)
    Caused by: java.lang.ExceptionInInitializerError
            at org.jetbrains.kotlin.com.intellij.util.exception.FrequentErrorLogger.report(FrequentErrorLogger.java:47)
            at org.jetbrains.kotlin.com.intellij.util.exception.FrequentErrorLogger.info(FrequentErrorLogger.java:43)
            at org.jetbrains.kotlin.com.intellij.psi.impl.DebugUtil.handleUnspecifiedTrace(DebugUtil.java:628)
            at org.jetbrains.kotlin.com.intellij.psi.impl.DebugUtil.currentInvalidationTrace(DebugUtil.java:620)
            at org.jetbrains.kotlin.com.intellij.psi.impl.DebugUtil.calcInvalidationTrace(DebugUtil.java:614)
            at org.jetbrains.kotlin.com.intellij.psi.impl.DebugUtil.onInvalidated(DebugUtil.java:585)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.TreeElement.onInvalidated(TreeElement.java:226)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.TreeElement.rawRemoveUpToWithoutNotifications(TreeElement.java:388)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.TreeElement.rawRemoveUpTo(TreeElement.java:342)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement.remove(CompositeElement.java:775)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement.lambda$removeChildrenInner$4(CompositeElement.java:797)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.ChangeUtil$1.runInner(ChangeUtil.java:147)
            at org.jetbrains.kotlin.com.intellij.pom.impl.PomTransactionBase.run(PomTransactionBase.java:28)
            at com.pinterest.ktlint.core.internal.FormatPomModel.runTransaction(KotlinPsiFileFactory.kt:121)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.ChangeUtil.prepareAndRunChangeAction(ChangeUtil.java:142)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement.removeChildrenInner(CompositeElement.java:796)
            at org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement.removeRange(CompositeElement.java:611)
            at com.pinterest.ktlint.ruleset.standard.ImportOrderingRule.visit(ImportOrderingRule.kt:235)
            at com.pinterest.ktlint.core.KtLint$format$1.invoke(KtLint.kt:351)
            at com.pinterest.ktlint.core.KtLint$format$1.invoke(KtLint.kt:344)
            at com.pinterest.ktlint.core.VisitorProvider$sequentialVisitor$1$1$1$1.invoke(VisitorProvider.kt:102)
            at com.pinterest.ktlint.core.VisitorProvider$sequentialVisitor$1$1$1$1.invoke(VisitorProvider.kt:102)
            at com.pinterest.ktlint.core.ast.PackageKt.visit(package.kt:229)
            at com.pinterest.ktlint.core.ast.PackageKt.visit(package.kt:230)
            at com.pinterest.ktlint.core.VisitorProvider$sequentialVisitor$1.invoke(VisitorProvider.kt:102)
            at com.pinterest.ktlint.core.VisitorProvider$sequentialVisitor$1.invoke(VisitorProvider.kt:94)
            at com.pinterest.ktlint.core.KtLint.format(KtLint.kt:344)
            at com.pinterest.ktlint.internal.FileUtilsKt.formatFile(FileUtils.kt:221)
            at com.pinterest.ktlint.KtlintCommandLine.process(Main.kt:396)
            at com.pinterest.ktlint.KtlintCommandLine.access$process(Main.kt:95)
            at com.pinterest.ktlint.KtlintCommandLine$lintFiles$3.invoke$lambda-1(Main.kt:311)
            at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
            at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
            at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
            at java.base/java.lang.Thread.run(Thread.java:833)
    Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private transient java.lang.Object java.lang.Throwable.backtrace accessible: module java.base does not "opens java.lang" to unnamed module @76628072
            at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
            at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
            at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:178)
            at java.base/java.lang.reflect.Field.setAccessible(Field.java:172)
            at org.jetbrains.kotlin.com.intellij.util.ReflectionUtil.findFieldInHierarchy(ReflectionUtil.java:154)
            at org.jetbrains.kotlin.com.intellij.util.ReflectionUtil.getDeclaredField(ReflectionUtil.java:279)
            at org.jetbrains.kotlin.com.intellij.openapi.util.objectTree.ThrowableInterner.<clinit>(ThrowableInterner.java:88)
            ... 35 more
    
    FAILURE: Build failed with an exception.
    

    Steps to Reproduce

    ktlint.gradle:

    apply plugin: 'java'
    
    repositories {
        mavenCentral()
    }
    
    configurations {
        ktlint
    }
    
    dependencies {
        ktlint("com.pinterest:ktlint:0.44.0") {
            attributes {
                attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))
            }
        }
        // additional 3rd party ruleset(s) can be specified here
        // just add them to the classpath (e.g. ktlint 'groupId:artifactId:version') and
        // ktlint will pick them up
    }
    
    task ktlint(type: JavaExec, group: "verification") {
        description = "Check Kotlin code style."
        classpath = configurations.ktlint
        mainClass.set("com.pinterest.ktlint.Main")
        args "-F", "**/src/**/*.kt", "!**/genMain/**", "!**/genTest/**"
        // to generate report in checkstyle format prepend following args:
        // "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/ktlint.xml"
        // to add a baseline to check against prepend following args:
        // "--baseline=ktlint-baseline.xml"
        // see https://github.com/pinterest/ktlint#usage for more
    }
    check.dependsOn ktlint
    
    task ktlintFormat(type: JavaExec, group: "formatting") {
        description = "Fix Kotlin code style deviations."
        classpath = configurations.ktlint
        mainClass.set("com.pinterest.ktlint.Main")
        args "-F", "**/src/**/*.kt", "!**/genMain/**", "!**/genTest/**"
    }
    

    Your Environment

    • Version of ktlint used: 0.44.0
    • Name and version (or code for custom task) of integration used (Gradle plugin, Maven plugin, command line, custom Gradle task):
    • Version of Gradle used (if applicable): 7.4
    • Operating System and version: Latest MacOS Monterey
    • Link to your project (if it's a public repository): https://github.com/ScottPierce/kotlin-html/tree/scott/Kotlin_1_6
    • Java Version:
    java --version        
    openjdk 17.0.2 2022-01-18 LTS
    OpenJDK Runtime Environment Corretto-17.0.2.8.1 (build 17.0.2+8-LTS)
    OpenJDK 64-Bit Server VM Corretto-17.0.2.8.1 (build 17.0.2+8-LTS, mixed mode, sharing)
    
    opened by ScottPierce 25
  • Unused imports are not removed with .* in the end

    Unused imports are not removed with .* in the end

    .editorconfig:

    # top-most EditorConfig file
    root = true
    
    [**.{kt,kts}]
    
    indent_size=4
    insert_final_newline=true
    max_line_length=off
    
    # Comma-separated list of rules to disable
    disabled_rules=no-wildcard-imports,experimental:argument-list-wrapping,filename,parameter-list-wrapping,spacing-between-declarations-with-annotations
    
    ij_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
    
    import io.ktor.client.*
    import io.ktor.client.statement.*
    import java.util.*
    

    import java.util.* - not using

    Your Environment

    • Version of ktlint used: "10.2.0"
    • Name and version (or code for custom task) of integration used (Gradle plugin, Maven plugin, command line, custom Gradle task):
    • Version of Gradle used (if applicable): 6.9.1
    • Operating System and version: MacOS
    • Link to your project (if it's a public repository):
    bug 
    opened by YauheniPo 23
  • Detect filename is not compliant with PascalCase convention

    Detect filename is not compliant with PascalCase convention

    Hi, I found that FilenameRule does not check PascalCase convention mentioned in https://kotlinlang.org/docs/coding-conventions.html#source-file-names What do you think? Thx Ivos

    opened by bedla 22
  • Is it possible to enforce parameters are on their own line?

    Is it possible to enforce parameters are on their own line?

    I found myself in a scenario where I had multiple parameter on one line, with others on a different line, like this:

    fun test(one: String, two: String, three: String, four: String) {
    }
    
    fun callTest() {
        test(
            "One",
            "Two", "Three", "Four"
        )
    }
    

    KtLint actually passes this, because there is a new line after the opening ( and one before the closing ), but I still think it's weird to have one parameter on one line and three on the other.

    I'd really prefer it be an all or nothing thing:

    // This
    test("One", "Two", "Three", "Four")
    // Or
    test(
        "One",
        "Two",
        "Three",
        "Four"
    )
    

    Any thoughts on a way to enforce this, if it's possible?

    bug 
    opened by AdamMc331 22
  • Logger failes to initialize when not providing the Classic Logback Logger in 0.45.0

    Logger failes to initialize when not providing the Classic Logback Logger in 0.45.0

    Expected Behavior

    It should work

    Observed Behavior

    This failure occurs (when using via Spotless)

    Step 'ktlint' found problem in 'src/main/java/slack/appprofile/di/AppProfileModule.kt':
    --
      | Could not initialize class com.pinterest.ktlint.core.internal.EditorConfigLoaderKt
      | java.lang.NoClassDefFoundError: Could not initialize class com.pinterest.ktlint.core.internal.EditorConfigLoaderKt
      | at com.pinterest.ktlint.core.internal.EditorConfigLoader.loadPropertiesForFile(EditorConfigLoader.kt:111)
      | at com.pinterest.ktlint.core.KtLint.prepareCodeForLinting(KtLint.kt:234)
      | at com.pinterest.ktlint.core.KtLint.format(KtLint.kt:344)
      | at com.pinterest.ktlint.core.KtLint.format(KtLint.kt:319)
      | at com.pinterest.ktlint.core.KtLint.format(KtLint.kt:315)
      | at com.diffplug.spotless.glue.ktlint.KtlintFormatterFunc.applyWithFile(KtlintFormatterFunc.java:60)
      | at com.diffplug.spotless.FormatterFunc$NeedsFile.apply(FormatterFunc.java:154)
      | at com.diffplug.spotless.FormatterStepImpl$Standard.format(FormatterStepImpl.java:78)
      | at com.diffplug.spotless.FormatterStep$Strict.format(FormatterStep.java:88)
      | at com.diffplug.spotless.Formatter.compute(Formatter.java:230)
      | at com.diffplug.spotless.PaddedCell.calculateDirtyState(PaddedCell.java:203)
      | at com.diffplug.spotless.PaddedCell.calculateDirtyState(PaddedCell.java:190)
      | at com.diffplug.gradle.spotless.SpotlessTaskImpl.processInputFile(SpotlessTaskImpl.java:92)
      | at com.diffplug.gradle.spotless.SpotlessTaskImpl.performAction(SpotlessTaskImpl.java:78)
    

    Steps to Reproduce

    Use editorconfig and ktlint 0.45.0 in a project

    Your Environment

    • Version of ktlint used: 0.45.0
    • Relevant parts of the .editorconfig settings
    [*]
    charset=utf-8
    end_of_line=lf
    insert_final_newline=true
    trim_trailing_whitespace=true
    indent_style=space
    indent_size=4
    
    [*.proto]
    indent_size=2
    
    [*.java]
    indent_size=2
    
    [*.json]
    indent_size=2
    
    [*.{kt,kts}]
    indent_size=2
    continuation_indent_size=2
    disabled_rules=final-newline
    
    [{*.yml,*.yaml}]
    indent_size=2
    
    • Name and version (or code for custom task) of integration used (Gradle plugin, Maven plugin, command line, custom Gradle task): Spotless 6.3.0
    • Version of Gradle used (if applicable): 7.4.1
    • Operating System and version: macOS Monterey
    opened by ZacSweers 21
  • KtLint CLI 0.43 doesn't work with JDK 1.8

    KtLint CLI 0.43 doesn't work with JDK 1.8

    Gentoo linux latest Ktlint 0.43 binary from you repository Run in clean kotlin project

    Command: git diff --name-only --cached --relative | grep '\.kt[s"]\?$' | xargs ktlint --relative

    Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ExceptionInInitializerError
            at java.util.concurrent.FutureTask.report(FutureTask.java:122)
            at java.util.concurrent.FutureTask.get(FutureTask.java:192)
            at com.pinterest.ktlint.KtlintCommandLine.parallel(Main.kt:576)
            at com.pinterest.ktlint.KtlintCommandLine.parallel$default(Main.kt:548)
            at com.pinterest.ktlint.KtlintCommandLine.lintFiles(Main.kt:298)
            at com.pinterest.ktlint.KtlintCommandLine.run(Main.kt:262)
            at com.pinterest.ktlint.Main.main(Main.kt:70)
    Caused by: java.lang.ExceptionInInitializerError
            at com.pinterest.ktlint.internal.FileUtilsKt.lintFile(FileUtils.kt:172)
            at com.pinterest.ktlint.KtlintCommandLine.process(Main.kt:395)
            at com.pinterest.ktlint.KtlintCommandLine.access$process(Main.kt:89)
            at com.pinterest.ktlint.KtlintCommandLine$lintFiles$3.invoke$lambda-0(Main.kt:289)
            at java.util.concurrent.FutureTask.run(FutureTask.java:266)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at java.lang.Thread.run(Thread.java:748)
    Caused by: java.lang.RuntimeException: java.util.zip.ZipException: invalid distance too far back
            at org.jetbrains.kotlin.com.intellij.util.ExceptionUtil.rethrow(ExceptionUtil.java:116)
            at org.jetbrains.kotlin.com.intellij.ide.plugins.PluginDescriptorLoader.loadDescriptorFromJar(PluginDescriptorLoader.java:107)
            at org.jetbrains.kotlin.com.intellij.ide.plugins.PluginManagerCore.registerExtensionPointAndExtensions(PluginManagerCore.java:1401)
            at org.jetbrains.kotlin.com.intellij.core.CoreApplicationEnvironment.registerExtensionPointAndExtensions(CoreApplicationEnvironment.java:266)
            at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.registerApplicationExtensionPointsAndExtensionsFrom(KotlinCoreEnvironment.kt:575)
            at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createApplicationEnvironment(KotlinCoreEnvironment.kt:540)
            at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.getOrCreateApplicationEnvironment(KotlinCoreEnvironment.kt:497)
            at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.getOrCreateApplicationEnvironmentForProduction(KotlinCoreEnvironment.kt:485)
            at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:429)
            at com.pinterest.ktlint.core.internal.KotlinPsiFileFactoryKt.initPsiFileFactory(KotlinPsiFileFactory.kt:32)
            at com.pinterest.ktlint.core.KtLint.<clinit>(KtLint.kt:42)
            ... 8 more
    Caused by: java.util.zip.ZipException: invalid distance too far back
            at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
            at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
            at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
            at org.jetbrains.kotlin.com.intellij.openapi.vfs.CharsetToolkit.inputStreamSkippingBOM(CharsetToolkit.java:116)
            at org.jetbrains.kotlin.com.intellij.openapi.util.JDOMUtil.load(JDOMUtil.java:351)
            at org.jetbrains.kotlin.com.intellij.ide.plugins.PluginDescriptorLoader.loadDescriptorFromJar(PluginDescriptorLoader.java:87)
            ... 17 more
    
    

    Command: git diff --name-only --cached --relative | grep '\.kt[s"]\?$' | xargs ktlint .

    Error:

    Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Could not initialize class com.pinterest.ktlint.core.KtLint
            at java.util.concurrent.FutureTask.report(FutureTask.java:122)
            at java.util.concurrent.FutureTask.get(FutureTask.java:192)
            at com.pinterest.ktlint.KtlintCommandLine.parallel(Main.kt:576)
            at com.pinterest.ktlint.KtlintCommandLine.parallel$default(Main.kt:548)
            at com.pinterest.ktlint.KtlintCommandLine.lintFiles(Main.kt:298)
            at com.pinterest.ktlint.KtlintCommandLine.run(Main.kt:262)
            at com.pinterest.ktlint.Main.main(Main.kt:70)
    Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.pinterest.ktlint.core.KtLint
            at com.pinterest.ktlint.internal.FileUtilsKt.lintFile(FileUtils.kt:172)
            at com.pinterest.ktlint.KtlintCommandLine.process(Main.kt:395)
            at com.pinterest.ktlint.KtlintCommandLine.access$process(Main.kt:89)
            at com.pinterest.ktlint.KtlintCommandLine$lintFiles$3.invoke$lambda-0(Main.kt:289)
            at java.util.concurrent.FutureTask.run(FutureTask.java:266)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at java.lang.Thread.run(Thread.java:748)
    
    

    Command: ktlint

    Error:

    Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: Could not initialize class com.pinterest.ktlint.core.KtLint
            at java.util.concurrent.FutureTask.report(FutureTask.java:122)
            at java.util.concurrent.FutureTask.get(FutureTask.java:192)
            at com.pinterest.ktlint.KtlintCommandLine.parallel(Main.kt:576)
            at com.pinterest.ktlint.KtlintCommandLine.parallel$default(Main.kt:548)
            at com.pinterest.ktlint.KtlintCommandLine.lintFiles(Main.kt:298)
            at com.pinterest.ktlint.KtlintCommandLine.run(Main.kt:262)
            at com.pinterest.ktlint.Main.main(Main.kt:70)
    Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.pinterest.ktlint.core.KtLint
            at com.pinterest.ktlint.internal.FileUtilsKt.lintFile(FileUtils.kt:172)
            at com.pinterest.ktlint.KtlintCommandLine.process(Main.kt:395)
            at com.pinterest.ktlint.KtlintCommandLine.access$process(Main.kt:89)
            at com.pinterest.ktlint.KtlintCommandLine$lintFiles$3.invoke$lambda-0(Main.kt:289)
            at java.util.concurrent.FutureTask.run(FutureTask.java:266)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at java.lang.Thread.run(Thread.java:748)
    
    bug 
    opened by JajaComp 21
  • ktlint command: `./ktlint

    ktlint command: `./ktlint "**/src/**/*.kt" -F` removes symbol `;` from the end of ENUM values

    Expected Behavior

    enum class may contain ; at end of list values

    Observed Behavior

    ktlint command: ./ktlint "**/src/**/*.kt" -F removes symbol ; from the end of list values

    Steps to Reproduce

    Create enum MyEnums.kt:

    enum class MyEnums  {
        FIRST,
        SECOND;
        fun isFirst(){
            this == MyEnums.FIRST
        }
    }
    

    run command: ./ktlint "**/src/**/*.kt" -F in result:

    enum class MyEnums  {
        FIRST,
        SECOND // symbol `;` was removed , compile error occurs 
    
        fun isFirst(){
            this == MyEnums.FIRST
        }
    }
    

    Your Environment

    • Version of ktlint used: 0.48.0
    • Version of Gradle used (if applicable):
    classpath 'com.android.tools.build:gradle:7.3.1'
    distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
    
    • Operating System and version: Ubuntu 20.04.5 LTS
    opened by Kolyall 0
  • Fix another issue with annotations incorrectly being forced to be multi-line

    Fix another issue with annotations incorrectly being forced to be multi-line

    Similar to #1688, an array of annotations would be forced to be multi-line if any of the entries had a parameter.

    • [x] PR description added
    • [x] tests are added
    • [ ] KtLint has been applied on source code itself and violations are fixed
    • [ ] documentation is updated
    • [x] CHANGELOG.md is updated
    opened by shashachu 0
  • 0.48.0 does not allow nordic chars åäöåæø in package-names

    0.48.0 does not allow nordic chars åäöåæø in package-names

    When upgrading from 0.47.1 to 0.48.0, ktlint complains on package names containing åæø.

    Expected Behavior

    Expecting æøå to be accepted

    Observed Behavior

    Package name contains a disallowed character (cannot be auto-corrected) (package-name)

    Steps to Reproduce

    Create class Bar in package with name føø and run mvn antrun:run@ktlint

    Your Environment

    • Version of ktlint used: 0.48.0
    • Relevant parts of the .editorconfig settings
    • Name and version (or code for custom task) of integration used (Gradle plugin, Maven plugin, command line, custom Gradle task): Apache Maven 3.8.1
    • Operating System and version: macOS Ventura 13.1
    opened by olekvernberg 4
  • Format parameters in lambda

    Format parameters in lambda

    It looks like ktlint 0.47.1 is not accepting that format in my project:

    fun combine(a: Any, b: Any, c: (Any, Any) -> Unit) {
      c(a, b)
    }
    
    class Foo {
      fun foo() {
        combine(
          Any(),
          Any()
        ) { a,
            b ->
          TODO()
        }
      }
    }
    

    .editorconfig

    [*.{kt,kts}]
    indent_size = 2
    indent_style = space
    

    error

    Foo.kt:11:1: Unexpected indentation (8) (should be 6) (indent)
    

    Originally posted by @eygraber in https://github.com/pinterest/ktlint/issues/1681#issuecomment-1352590673

    opened by paul-dingemans 0
  • Unused import rules does not remove all imports the same as Intellij(Android Studio)

    Unused import rules does not remove all imports the same as Intellij(Android Studio)

    Expected Behavior

    I have found that the unused import rule does not remove all unused imports. I think this is related or the same issue as https://github.com/pinterest/ktlint/issues/1587.

    Observed Behavior

    The imports not removed are import co.[ID].data.session.isLoggedIn import kotlinx.coroutines.flow.collect import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue They are removed via android studio optimize imports but not by ktlint. I ran ktlint 48 through the terminal to test

    Posted in the kotlin slack https://kotlinlang.slack.com/archives/CKS3XG0LS/p1672347793114019 It appears that some imports are not going to be removed.

    Summary

    Does that mean its not worth the effort or its literally impossible? Is there something that can get exposed to you to make this possible? If the issue is that it would require a large refactor I think it would be valuable to know where in the code the limitation and how to resolve the limitation so someone can consider putting out a PR?

    Also should we update the documentation to reference the current limitations? I am not sure I understand the rules of the limitations

    opened by DavidCorrado 1
  • Interface experimental rule

    Interface experimental rule

    Description

    Add interface "Rule.Experimental" to mark a rule as an experimental rule. Rules no longer have to be part of the "experimental" rule set to be treated as an experimental rule. This allows experimental rules to be defined in any rule set. Whenever a rule is no longer experimental it does not need to be moved to a non-experimental rule set. Benefit is that users of that rule, do not need to change ktlint disable directives.

    Simplify code by moving logic from QualifiedRuleId to Rule. All logic regarding qualified rule (set) id is now kept together in once class.

    The 'experimentalrule set of Ktlint has been merged with thestandard` rule set.

    Checklist

    • [X] PR description added
    • [ ] tests are added
    • [X] KtLint has been applied on source code itself and violations are fixed
    • [X] documentation is updated
    • [X] CHANGELOG.md is updated

    In case of adding a new rule:

    opened by paul-dingemans 0
Releases(0.48.1)
  • 0.48.1(Jan 3, 2023)

    Added

    Removed

    Fixed

    • An enumeration class having a primary constructor and in which the list of enum entries is followed by a semicolon then do not remove the semicolon in case it is followed by code element no-semi (#1733)
    • Add API so that KtLint API consumer is able to process a Kotlin script snippet without having to specify a file path (#1738)
    • Disable the standard:filename rule whenever Ktlint CLI is run with option --stdin (#1742)
    • Fix initialization of the logger when --log-level is specified. Throw exception when an invalid value is passed. (#1749)
    • Fix loading of custom rule set JARs.
    • Rules provided via a custom rule set JAR (Ktlint CLI) or by an API provider are enabled by default. Only rules in the experimental rule set are disabled by default. (#1747)

    Changed

    • Update Kotlin development version to 1.8.0 and Kotlin version to 1.8.0.
    Source code(tar.gz)
    Source code(zip)
    ktlint(62.13 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.48.0(Dec 15, 2022)

    [0.48.0] - 2022-12-15

    Indent rule

    The indent rule has been rewritten from scratch. Solving problems in the old algorithm was very difficult. With the new algorithm this becomes a lot easier. Although the new implementation of the rule has been compared against several open source projects containing over 400,000 lines of code, it is still likely that new issues will be discovered. Please report your indentation issues so that these can be fixed as well.

    .editorconfig property to disable rules

    In the previous release (0.47.x), the .editorconfig property disabled_rules was deprecated and replaced with ktlint_disabled_rules. This latter property has now been deprecated as well in favour of a more flexible and better maintainable solution. Rule and rule sets can now be enabled/disabled with a separate property per rule (set). Please read deprecation of (ktlint_)disable_rules property for more information.

    The KtLint CLI has not been changed. Although you can still use parameter --experimental to enable KtLint's Experimental rule set, you might want to set .editorconfig property ktlint_experimental = enabled instead.

    API Changes & RuleSet providers

    If you are not an API consumer or Rule Set provider then you can skip this section.

    Class relocations

    Classes below have been relocated:

    • Class com.pinterest.ktlint.core.api.UsesEditorConfigProperties.EditorConfigProperty has been replaced with com.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty.
    • Class com.pinterest.ktlint.core.KtLintParseException has been replaced with com.pinterest.ktlint.core.api.KtLintParseException.
    • Class com.pinterest.ktlint.core.RuleExecutionException has been replaced with com.pinterest.ktlint.core.api.KtLintRuleException.
    • Class com.pinterest.ktlint.reporter.format.internal.Color has been moved to com.pinterest.ktlint.reporter.format.Color.
    • Class com.pinterest.ktlint.reporter.plain.internal.Color has been moved to com.pinterest.ktlint.reporter.plain.Color.

    Invoking lint and format

    This is the last release that supports the ExperimentalParams to invoke the lint and format functions of KtLint. The ExperimentalParams contains a mix of configuration settings which are not dependent on the file/code which is to be processed. Other parameters in that class describe the code/file to be processed but can be configured inconsistently (for example a file with name "foo.kt" could be marked as a Kotlin Script file).

    The static object KtLint is deprecated and replaced by class KtLintRuleEngine which is configured with KtLintRuleEngineConfiguration. The instance of the KtLintRuleEngine is intended to be reused for scanning all files in a project and should not be recreated per file.

    Both lint and format are simplified and can now be called for a code block or for an entire file.

    import java.io.File
    
    // Define a reusable instance of the KtLint Rule Engine
    val ktLintRuleEngine = KtLintRuleEngine(
      // Define configuration
    )
    
    
    // Process a collection of files
    val files: Set<File> // Collect files in a convenient way
    files.forEach(file in files) {
        ktLintRuleEngine.lint(file) {
            // Handle lint violations
        }
    }
    
    // or process a code sample for a given filepath
    ktLintRuleEngine.lint(
      code = "code to be linted",
      filePath = Path("/path/to/source/file")
    ) {
      // Handle lint violations
    }
    

    Retrieve .editorconfigs

    The list of .editorconfig files which will be accessed by KtLint when linting or formatting a given path can now be retrieved with the new API KtLint.editorConfigFilePaths(path: Path): List<Path>.

    This API can be called with either a file or a directory. It's intended usage is that it is called once with the root directory of a project before actually linting or formatting files of that project. When called with a directory path, all .editorconfig files in the directory or any of its subdirectories (except hidden directories) are returned. In case the given directory does not contain an .editorconfig file or if it does not contain the root=true setting, the parent directories are scanned as well until a root .editorconfig file is found.

    Calling this API with a file path results in the .editorconfig files that will be accessed when processing that specific file. In case the directory in which the file resides does not contain an .editorconfig file or if it does not contain the root=true setting, the parent directories are scanned until a root .editorconfig file is found.

    Psi filename replaces FILE_PATH_USER_DATA_KEY

    Constant KtLint.FILE_PATH_USER_DATA_KEY is deprecated and will be removed in KtLint version 0.49.0. The file name will be passed correctly to the node with element type FILE and can be retrieved as follows:

    if (node.isRoot()) {
        val fileName = (node.psi as? KtFile)?.name
        ...
    }
    

    Added

    • Wrap blocks in case the max line length is exceeded or in case the block contains a new line wrapping (#1643)
    • patterns can be read in from stdin with the --patterns-from-stdin command line options/flags (#1606)
    • Add basic formatting for context receiver in indent rule and new experimental rule context-receiver-wrapping (#1672)
    • Add naming rules for classes and objects (class-naming), functions (function-naming) and properties (property-naming) (#44)
    • Add new built-in reporter plain-summary which prints a summary the number of violation which have been autocorrected or could not be autocorrected, both split by rule.

    Fixed

    • Let a rule process all nodes even in case the rule is suppressed for a node so that the rule can update the internal state (#1644)
    • Read .editorconfig when running CLI with options --stdin and --editorconfig (#1651)
    • Do not add a trailing comma in case a multiline function call argument is found but no newline between the arguments trailing-comma-on-call-site (#1642)
    • Add missing ktlint_disabled_rules to exposed editorConfigProperties (#1671)
    • Do not add a second trailing comma, if the original trailing comma is followed by a KDOC trailing-comma-on-declaration-site and trailing-comma-on-call-site (#1676)
    • A function signature preceded by an annotation array should be handled similar as function preceded by a singular annotation function-signature (#1690)
    • Fix offset of annotation violations
    • Fix line offset when blank line found between class and primary constructor
    • Remove needless blank line between class followed by EOL, and primary constructor
    • Fix offset of unexpected linebreak before assignment
    • Remove whitespace before redundant semicolon if the semicolon is followed by whitespace

    Changed

    • Update Kotlin development version to 1.8.0-RC and Kotlin version to 1.7.21.
    • The default value for trailing comma's on call site is changed to true unless the android codestyle is enabled. Note that KtLint from a consistency viewpoint enforces the trailing comma on call site while default IntelliJ IDEA formatting only allows the trailing comma but leaves it up to the developer's discretion. (#1670)
    • The default value for trailing comma's on declaration site is changed to true unless the android codestyle is enabled. Note that KtLint from a consistency viewpoint enforces the trailing comma on declaration site while default IntelliJ IDEA formatting only allows the trailing comma but leaves it up to the developer's discretion. (#1669)
    • CLI options --debug, --trace, --verbose and -v are replaced with --log-level=<level> or the short version `-l=, see CLI log-level. (#1632)
    • In CLI, disable logging entirely by setting --log-level=none or -l=none (#1652)
    • Rewrite indent rule. Solving problems in the old algorithm was very difficult. With the new algorithm this becomes a lot easier. Although the new implementation of the rule has been compared against several open source projects containing over 400,000 lines of code, it is still likely that new issues will be discovered. Please report your indentation issues so that these can be fixed as well. (#1682, #1321, #1200, #1562, #1563, #1639)
    • Add methods "ASTNode.upsertWhitespaceBeforeMe" and "ASTNode.upsertWhitespaceAfterMe" as replacements for "LeafElement.upsertWhitespaceBeforeMe" and "LeafElement.upsertWhitespaceAfterMe". The new methods are more versatile and allow code to be written more readable in most places. (#1687)
    • Rewrite indent rule. Solving problems in the old algorithm was very difficult. With the new algorithm this becomes a lot easier. Although the new implementation of the rule has been compared against several open source projects containing over 400,000 lines of code, it is still likely that new issues will be discovered. Please report your indentation issues so that these can be fixed as well. (#1682, #1321, #1200, #1562, #1563, #1639, #1688)
    • Add support for running tests on java 19, remove support for running tests on java 18.
    • Update io.github.detekt.sarif4k:sarif4k version to 0.2.0 (#1701).
    Source code(tar.gz)
    Source code(zip)
    ktlint(61.85 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.47.1(Sep 7, 2022)

    [0.47.1] - 2022-09-07

    Fixed

    • Do not add trailing comma in empty parameter/argument list with comments (trailing-comma-on-call-site, trailing-comma-on-declaration-site) (#1602)
    • Fix class cast exception when specifying a non-string editorconfig setting in the default ".editorconfig" (#1627)
    • Fix indentation before semi-colon when it is pushed down after inserting a trailing comma (#1609)
    • Do not show deprecation warning about property "disabled_rules" when using CLi-parameter --disabled-rules (#1599)
    • Traversing directory hierarchy at Windows (#1600)
    • Ant-style path pattern support (#1601)
    • Apply @file:Suppress on all toplevel declarations (#1623)

    Changed

    • Display warning instead of error when no files are matched, and return with exit code 0. (#1624)
    Source code(tar.gz)
    Source code(zip)
    ktlint(60.67 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.47.0(Aug 19, 2022)

    [0.47.0] - 2022-08-19

    API Changes & RuleSet providers

    If you are not an API consumer nor a RuleSet provider, then you can safely skip this section. Otherwise, please read below carefully and upgrade your usage of ktlint. In this and coming releases, we are changing and adapting important parts of our API in order to increase maintainability and flexibility for future changes. Please avoid skipping a releases as that will make it harder to migrate.

    Rule lifecycle hooks / deprecate RunOnRootOnly visitor modifier

    Up until ktlint 0.46 the Rule class provided only one life cycle hook. This "visit" hook was called in a depth-first-approach on all nodes in the file. A rule like the IndentationRule used the RunOnRootOnly visitor modifier to call this lifecycle hook for the root node only in combination with an alternative way of traversing the ASTNodes. Downside of this approach was that suppression of the rule on blocks inside a file was not possible (#631). More generically, this applied to all rules, applying alternative traversals of the AST.

    The Rule class now offers new life cycle hooks:

    • beforeFirstNode: This method is called once before the first node is visited. It can be used to initialize the state of the rule before processing of nodes starts. The ".editorconfig" properties (including overrides) are provided as parameter.
    • beforeVisitChildNodes: This method is called on a node in AST before visiting its child nodes. This is repeated recursively for the child nodes resulting in a depth first traversal of the AST. This method is the equivalent of the "visit" life cycle hooks. However, note that in KtLint 0.48, the UserData of the rootnode no longer provides access to the ".editorconfig" properties. This method can be used to emit Lint Violations and to autocorrect if applicable.
    • afterVisitChildNodes: This method is called on a node in AST after all its child nodes have been visited. This method can be used to emit Lint Violations and to autocorrect if applicable.
    • afterLastNode: This method is called once after the last node in the AST is visited. It can be used for teardown of the state of the rule.

    Optionally, a rule can stop the traversal of the remainder of the AST whenever the goal of the rule has been achieved. See KDoc on Rule class for more information.

    The "visit" life cycle hook will be removed in Ktlint 0.48. In KtLint 0.47 the "visit" life cycle hook will be called only when hook "beforeVisitChildNodes" is not overridden. It is recommended to migrate to the new lifecycle hooks in KtLint 0.47. Please create an issue, in case you need additional assistence to implement the new life cycle hooks in your rules.

    Ruleset providing by Custom Rule Set Provider

    The KtLint engine needs a more fine-grained control on the instantiation of new Rule instances. Currently, a new instance of a rule can be created only once per file. However, when formatting files the same rule instance is reused for a second processing iteration in case a Lint violation has been autocorrected. By re-using the same rule instance, state of that rule might leak from the first to the second processing iteration.

    Providers of custom rule sets have to migrate the custom rule set JAR file. The current RuleSetProvider interface which is implemented in the custom rule set is deprecated and marked for removal in KtLint 0.48. Custom rule sets using the old RuleSetProvider interface will not be run in KtLint 0.48 or above.

    For now, it is advised to implement the new RuleSetProviderV2 interface without removing the old RuleSetProvider interface. In this way, KtLint 0.47 and above use the RuleSetProviderV2 interface and ignore the old RuleSetProvider interface completely. KtLint 0.46 and below only use the old RuleSetProvider interface.

    Adding the new interface is straight forward, as can be seen below:

    // Current implementation
    public class CustomRuleSetProvider : RuleSetProvider {
        override fun get(): RuleSet = RuleSet(
            "custom",
            CustomRule1(),
            CustomRule2(),
        )
    }
    
    // New implementation
    public class CustomRuleSetProvider :
        RuleSetProviderV2(CUSTOM_RULE_SET_ID),
        RuleSetProvider {
        override fun get(): RuleSet =
            RuleSet(
                CUSTOM_RULE_SET_ID,
                CustomRule1(),
                CustomRule2()
            )
    
        override fun getRuleProviders(): Set<RuleProvider> =
            setOf(
                RuleProvider { CustomRule1() },
                RuleProvider { CustomRule2() }
            )
    
        private companion object {
            const val CUSTOM_RULE_SET_ID = custom"
        }
    }
    
    

    Also note that file 'resource/META-INF/services/com.pinterest.ktlint.core.RuleSetProviderV2' needs to be added. In case your custom rule set provider implements both RuleSetProvider and RuleSetProviderV2, the resource directory contains files for both implementation. The content of those files is identical as the interfaces are implemented on the same class.

    Once above has been implemented, rules no longer have to clean up their internal state as the KtLint rule engine can request a new instance of the Rule at any time it suspects that the internal state of the Rule is tampered with (e.g. as soon as the Rule instance is used for traversing the AST).

    Rule set providing by API Consumer

    The KtLint engine needs a more fine-grained control on the instantiation of new Rule instances. Currently, a new instance of a rule can be created only once per file. However, when formatting files the same rule instance is reused for a second processing iteration in case a Lint violation has been autocorrected. By re-using the same rule instance, state of that rule might leak from the first to the second processing iteration.

    The ExperimentalParams parameter which is used to invoke "KtLint.lint" and "KtLint.format" contains a new parameter "ruleProviders" which will replace the "ruleSets" parameter in KtLint 0.48. Exactly one of those parameters should be a non-empty set. It is preferred that API consumers migrate to using "ruleProviders".

    // Old style using "ruleSets"
    KtLint.format(
        KtLint.ExperimentalParams(
            ...
            ruleSets = listOf(
                RuleSet(
                    "custom",
                    CustomRule1(),
                    CustomRule2()
                )
            ),
            ...
        )
    )
    
    // New style using "ruleProviders"
    KtLint.format(
        KtLint.ExperimentalParams(
            ...
            ruleProviders = setOf(
                RuleProvider { CustomRule1() },
                RuleProvider { CustomRule2() }
            ),
            cb = { _, _ -> }
        )
    )
    

    Once above has been implemented, rules no longer have to clean up their internal state as the KtLint rule engine can request a new instance of the Rule at any time it suspects that the internal state of the Rule is tampered with (e.g. as soon as the Rule instance is used for traversing the AST).

    Format callback

    The callback function provided as parameter to the format function is now called for all errors regardless whether the error has been autocorrected. Existing consumers of the format function should now explicitly check the autocorrected flag in the callback result and handle it appropriately (in most case this will be ignoring the callback results for which autocorrected has value true).

    CurrentBaseline

    Class com.pinterest.ktlint.core.internal.CurrentBaseline has been replaced with com.pinterest.ktlint.core.api.Baseline.

    Noteworthy changes:

    • Field baselineRules (nullable) is replaced with `lintErrorsPerFile (non-nullable).
    • Field baselineGenerationNeeded (boolean) is replaced with status (type Baseline.Status).

    The utility functions provided via com.pinterest.ktlint.core.internal.CurrentBaseline are moved to the new class. One new method List<LintError>.doesNotContain(lintError: LintError) is added.

    .editorconfig property "disabled_rules"

    The .editorconfig property disabled_rules (api property DefaultEditorConfigProperties.disabledRulesProperty) has been deprecated and will be removed in a future version. Use ktlint_disabled_rules (api property DefaultEditorConfigProperties.ktlintDisabledRulesProperty) instead as it more clearly identifies that ktlint is the owner of the property. This property is to be renamed in .editorconfig files and ExperimentalParams.editorConfigOverride.

    Although, Ktlint 0.47.0 falls back on property disabled_rules whenever ktlint_disabled_rules is not found, this result in a warning message being printed.

    Default/alternative .editorconfig

    Parameter "ExperimentalParams.editorConfigPath" is deprecated in favor of the new parameter "ExperimentalParams.editorConfigDefaults". When used in the old implementation this resulted in ignoring all ".editorconfig" files on the path to the file. The new implementation uses properties from the "editorConfigDefaults"parameter only when no ".editorconfig" files on the path to the file supplies this property for the filepath.

    API consumers can easily create the EditConfigDefaults by calling "EditConfigDefaults.load(path)" or creating it programmatically.

    Reload of .editorconfig file

    Some API Consumers keep a long-running instance of the KtLint engine alive. In case an .editorconfig file is changed, which was already loaded into the internal cache of the KtLint engine this change would not be taken into account by KtLint. One way to deal with this, was to clear the entire KtLint cache after each change in an .editorconfig file.

    Now, the API consumer can reload an .editorconfig. If the .editorconfig with given path is actually found in the cached, it will be replaced with the new value directly. If the file is not yet loaded in the cache, loading will be deferred until the file is actually requested again.

    Example:

    KtLint.reloadEditorConfigFile("/some/path/to/.editorconfig")
    

    Miscellaneous

    Several methods for which it is unlikely that they are used by API consumers have been marked for removal from the public API in KtLint 0.48.0. Please create an issue in case you have a valid business case to keep such methods in the public API.

    Added

    • Add format reporter. This reporter prints a one-line-summary of the formatting status per file. (#621).

    Fixed

    • Fix cli argument "--disabled_rules" (#1520).
    • A file which contains a single top level declaration of type function does not need to be named after the function but only needs to adhere to the PascalCase convention. filename (#1521).
    • Disable/enable IndentationRule on blocks in middle of file. (indent) #631
    • Allow usage of letters with diacritics in enum values and filenames (enum-entry-name-case, filename) (#1530).
    • Fix resolving of Java version when JAVA_TOOL_OPTIONS is set (#1543)
    • When a glob is specified then ensure that it matches files in the current directory and not only in subdirectories of the current directory (#1533).
    • Execute ktlint cli on default kotlin extensions only when an (existing) path to a directory is given. (#917).
    • Invoke callback on format function for all errors including errors that are autocorrected (#1491)
    • Merge first line of body expression with function signature only when it fits on the same line function-signature (#1527)
    • Add missing whitespace when else is on same line as true condition multiline-if-else (#1560)
    • Fix multiline if-statements multiline-if-else (#828)
    • Prevent class cast exception on ".editorconfig" property ktlint_code_style (#1559)
    • Handle trailing comma in enums trailing-comma (#1542)
    • Allow EOL comment after annotation (#1539)
    • Split rule trailing-comma into trailing-comma-on-call-site and trailing-comma-on-declaration-site (#1555)
    • Support globs containing directories in the ".editorconfig" supplied via CLI "--editorconfig" (#1551)
    • Fix indent of when entry with a dot qualified expression instead of simple value when trailing comma is required (#1519)
    • Fix whitespace between trailing comma and arrow in when entry when trailing comma is required (#1519)
    • Prevent false positive in parameter list for which the last value parameter is a destructuring declaration followed by a trailing comma wrapping (#1578)

    Changed

    • Print an error message and return with non-zero exit code when no files are found that match with the globs (#629).
    • Invoke callback on format function for all errors including errors that are autocorrected (#1491)
    • Improve rule annotation (#1574)
    • Rename .editorconfig property disabled_rules to ktlint_disabled_rules (#701)
    • Allow file and directory paths in CLI-parameter "--editorconfig" (#1580)
    • Update Kotlin development version to 1.7.20-beta and Kotlin version to 1.7.10.
    • Update release scripting to set version number in mkdocs documentation (#1575).
    • Update Gradle to 7.5.1 version

    Removed

    • Remove support to generate IntelliJ IDEA configuration files as this no longer fits the scope of the ktlint project (#701)
    Source code(tar.gz)
    Source code(zip)
    ktlint(60.53 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.46.1(Jun 21, 2022)

    [0.46.1] - 2022-06-21

    Minor release to address some regressions introduced in 0.46.0

    Fixed

    • Remove experimental flag -Xuse-k2 as it forces API Consumers to compile their projects with this same flag (#1506).
    • Account for separating spaces when parsing the disabled rules (#1508).
    • Do not remove space before a comment in a parameter list (#1509).
    • A delegate property which starts on the same line as the property declaration should not have an extra indentation indent (#1510)
    Source code(tar.gz)
    Source code(zip)
    ktlint(60.42 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.46.0(Jun 19, 2022)

    [0.46.0] - 2022-06-18

    Promoting experimental rules to standard

    The rules below are promoted from the experimental ruleset to the standard ruleset.

    • annotation
    • annotation-spacing
    • argument-list-wrapping
    • double-colon-spacing
    • enum-entry-name-case
    • multiline-if-else
    • no-empty-first-line-in-method-block
    • package-name
    • trailing-comma
    • spacing-around-angle-brackets
    • spacing-between-declarations-with-annotations
    • spacing-between-declarations-with-comments
    • unary-op-spacing

    Note that as a result of moving the rules that the prefix experimental: has to be removed from all references to this rule. Check references in:

    • The .editorconfig setting disabled_rules.
    • KtLint disable and enable directives.
    • The VisitorModifier.RunAfterRule.

    If your project did not run with the experimental ruleset enabled before, you might expect new lint violations to be reported. Please note that rules can be disabled via the the .editorconfig in case you do not want the rules to be applied on your project.

    API Changes & RuleSet providers

    If you are not an API user nor a RuleSet provider, then you can safely skip this section. Otherwise, please read below carefully and upgrade your usage of ktlint. In this and coming releases, we are changing and adapting important parts of our API in order to increase maintainability and flexibility for future changes. Please avoid skipping a releases as that will make it harder to migrate.

    Lint and formatting functions

    The lint and formatting changes no longer accept parameters of type Params but only ExperimentalParams. Also, the VisitorProvider parameter has been removed. Because of this, your integration with KtLint breaks. Based on feedback with ktlint 0.45.x, we now prefer to break at compile time instead of trying to keep the interface backwards compatible. Please raise an issue, in case you help to convert to the new API.

    Use of ".editorconfig" properties & userData

    The interface UsesEditorConfigProperties provides method getEditorConfigValue to retrieve a named .editorconfig property for a given ASTNode. When implementing this interface, the value editorConfigProperties needs to be overridden. Previously it was not checked whether a retrieved property was actually recorded in this list. Now, retrieval of unregistered properties results in an exception.

    Property Ktlint.DISABLED has been removed. The property value can now be retrieved as follows:

    astNode
        .getEditorConfigValue(DefaultEditorConfigProperties.disabledRulesProperty)
        .split(",")
    

    and be supplied via the ExperimentalParams as follows:

    ExperimentalParams(
        ...
        editorConfigOverride =  EditorConfigOverride.from(
          DefaultEditorConfigProperties.disabledRulesProperty to "some-rule-id,experimental:some-other-rule-id"
        )
        ...
    )
    

    Property Ktlint.ANDROID_USER_DATA_KEY has been removed. The property value can now be retrieved as follows:

    astNode
        .getEditorConfigValue(DefaultEditorConfigProperties.codeStyleProperty)
    

    and be supplied via the ExperimentalParams as follows:

    ExperimentalParams(
        ...
        editorConfigOverride =  EditorConfigOverride.from(
          DefaultEditorConfigProperties.codeStyleProperty to "android" 
        )
        ...
    )
    

    This property defaults to the official Kotlin code style when not set.

    Testing KtLint rules

    An AssertJ style API for testing KtLint rules (#1444) has been added. Usage of this API is encouraged in favor of using the old RuleExtension API. For more information, see KtLintAssertThat API

    Added

    • Add experimental rule for unexpected spacing between function name and opening parenthesis (spacing-between-function-name-and-opening-parenthesis) (#1341)
    • Add experimental rule for unexpected spacing in the parameter list (parameter-list-spacing) (#1341)
    • Add experimental rule for incorrect spacing around the function return type (function-return-type-spacing) (#1341)
    • Add experimental rule for unexpected spaces in a nullable type (nullable-type-spacing) (#1341)
    • Do not add a space after the typealias name (type-parameter-list-spacing) (#1435)
    • Add experimental rule for consistent spacing before the start of the function body (function-start-of-body-spacing) (#1341)
    • Suppress ktlint rules using @Suppress (more information) (#765)
    • Add experimental rule for rewriting the function signature (function-signature) (#1341)

    Fixed

    • Move disallowing blank lines in chained method calls from no-consecutive-blank-lines to new rule (no-blank-lines-in-chained-method-calls) (#1248)
    • Fix check of spacing in the receiver type of an anonymous function (#1440)
    • Allow comment on same line as super class in class declaration wrapping (#1457)
    • Respect git hooksPath setting (#1465)
    • Fix formatting of a property delegate with a dot-qualified-expression indent (#1340)
    • Keep formatting of for-loop in sync with default IntelliJ formatter (indent) and a newline in the expression in a for-statement should not force to wrap it wrapping (#1350)
    • Fix indentation of property getter/setter when the property has an initializer on a separate line indent (#1335)
    • When .editorconfig setting indentSize is set to value tab then return the default tab width as value for indentSize (#1485)
    • Allow suppressing all rules or a list of specific rules in the entire file with @file:Suppress(...) (#1029)

    Changed

    • Update Kotlin development version to 1.7.0 and Kotlin version to 1.7.0.
    • Update shadow plugin to 7.1.2 release
    • Update picocli to 4.6.3 release
    • A file containing only one (non private) top level declaration (class, interface, object, type alias or function) must be named after that declaration. The name also must comply with the Pascal Case convention. The same applies to a file containing one single top level class declaration and one ore more extension functions for that class. filename (#1004)
    • Promote experimental rules to standard rules set: annotation, annotation-spacing, argument-list-wrapping, double-colon-spacing, enum-entry-name-case, multiline-if-else, no-empty-first-line-in-method-block, package-name, traling-comma, spacing-around-angle-brackets, spacing-between-declarations-with-annotations, spacing-between-declarations-with-comments, unary-op-spacing (#1481)
    • The CLI parameter --android can be omitted when the .editorconfig property ktlint_code_style = android is defined
    Source code(tar.gz)
    Source code(zip)
    ktlint(60.42 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.45.2(Apr 6, 2022)

  • 0.45.1(Mar 21, 2022)

  • 0.45.0(Mar 18, 2022)

    [0.45.0] - 2022-03-18

    API Changes & RuleSet providers

    If you are not an API user nor a RuleSet provider, then you can safely skip this section. Otherwise, please read below carefully and upgrade your usage of ktlint. In this and coming releases, we are changing and adapting important parts of our API in order to increase maintainability and flexibility for future changes. Please avoid skipping a releases as that will make it harder to migrate.

    Retrieving ".editorconfig" property value

    This section is applicable when providing rules that depend on one or more values of ".editorconfig" properties. Property values should no longer be retrieved via EditConfig or directly via userData[EDITOR_CONFIG_USER_DATA_KEY]. Property values should now only be retrieved using method ASTNode.getEditorConfigValue(editorConfigProperty) of interface UsesEditorConfigProperties which is provided in this release. Starting from next release after the current release, the EditConfig and/or userData[EDITOR_CONFIG_USER_DATA_KEY] may be removed without further notice which will break your API or rule. To prevent disruption of your end user, you should migrate a.s.a.p.

    Added

    • Add experimental rule for unexpected spaces in a type reference before a function identifier (function-type-reference-spacing) (#1341)
    • Add experimental rule for incorrect spacing after a type parameter list (type-parameter-list-spacing) (#1366)
    • Add experimental rule to detect discouraged comment locations (discouraged-comment-location) (#1365)
    • Add rule to check spacing after fun keyword (fun-keyword-spacing) (#1362)
    • Add experimental rules for unnecessary spacing between modifiers in and after the last modifier in a modifier list (#1361)
    • New experimental rule for aligning the initial stars in a block comment when present (experimental:block-comment-initial-star-alignment (#297)
    • Respect .editorconfig property ij_kotlin_packages_to_use_import_on_demand (no-wildcard-imports) (#1272)
    • Add new experimental rules for wrapping of block comment (comment-wrapping) (#1403)
    • Add new experimental rules for wrapping of KDoc comment (kdoc-wrapping) (#1403)
    • Add experimental rule for incorrect spacing after a type parameter list (type-parameter-list-spacing) (#1366)
    • Expand check task to run tests on JDK 17 - "testOnJdk17"

    Fixed

    • Fix lint message to "Unnecessary long whitespace" (no-multi-spaces) (#1394)
    • Do not remove trailing comma after a parameter of type array in an annotation (experimental:trailing-comma) (#1379)
    • Do not delete blank lines in KDoc (no-trailing-spaces) (#1376)
    • Do not indent raw string literals that are not followed by either trimIndent() or trimMargin() (indent) (#1375)
    • Revert remove unnecessary wildcard imports as introduced in Ktlint 0.43.0 (no-unused-imports) (#1277), (#1393), (#1256)
    • (Possibly) resolve memory leak (#1216)
    • Initialize loglevel in Main class after parsing the CLI parameters (#1412)

    Changed

    • Print the rule id always in the PlainReporter (#1121)
    • All wrapping logic is moved from the indent rule to the new rule wrapping (as part of the standard ruleset). In case you currently have disabled the indent rule, you may want to reconsider whether this is still necessary or that you also want to disable the new wrapping rule to keep the status quo. Both rules can be run independent of each other. (#835)

    Removed

    Source code(tar.gz)
    Source code(zip)
    ktlint(57.71 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.44.0(Feb 15, 2022)

    [0.44.0] - 2022-02-15

    Please welcome paul-dingemans as an official maintainer of ktlint!

    Added

    • Use Gradle JVM toolchain with language version 8 to compile the project
    • Basic tests for CLI (#540)
    • Add experimental rule for unnecessary parentheses in function call followed by lambda (#1068)

    Fixed

    • Fix indentation of function literal (#1247)
    • Fix false positive in rule spacing-between-declarations-with-annotations (#1281)
    • Do not remove imports for same class when different alias is used (#1243)
    • Fix NoSuchElementException for property accessor (trailing-comma) (#1280)
    • Fix ClassCastException using ktlintFormat on class with KDoc (no-trailing-spaces) (#1270)
    • Do not remove trailing comma in annotation (#1297)
    • Do not remove import which is used as markdown link in KDoc only (no-unused-imports) (#1282)
    • Fix indentation of secondary constructor (indent) (#1222)
    • Custom gradle tasks with custom ruleset results in warning (#1269)
    • Fix alignment of arrow when trailing comma is missing in when entry (trailing-comma) (#1312)
    • Fix indent of delegated super type entry (indent) (#1210)
    • Improve indentation of closing quotes of a multiline raw string literal (indent) (#1262)
    • Trailing space should not lead to delete of indent of next line (no-trailing-spaces) (#1334)
    • Force a single line function type inside a nullable type to a separate line when the max line length is exceeded (parameter-list-wrapping) (#1255)
    • A single line function with a parameter having a lambda as default argument does not throw error (indent) (#1330)
    • Fix executable jar on Java 16+ (#1195)
    • Fix false positive unused import after autocorrecting a trailing comma (#1367)
    • Fix false positive indentation (parameter-list-wrapping, argument-list-wrapping) (#897, #1045, #1119, #1255, #1267, #1319, #1320, #1337
    • Force a single line function type inside a nullable type to a separate line when the max line length is exceeded (parameter-list-wrapping) (#1255)

    Changed

    • Update Kotlin version to 1.6.0 release
    • Add separate tasks to run tests on JDK 11 - "testOnJdk11"
    • Update Dokka to 1.6.0 release
    • Apply ktlint experimental rules on the ktlint code base itself.
    • Update shadow plugin to 7.1.1 release
    • Add Kotlin-logging backed by logback as logging framework (#589)
    • Update Gradle to 7.4 version
    Source code(tar.gz)
    Source code(zip)
    ktlint(57.65 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.43.2(Dec 1, 2021)

  • 0.43.0(Nov 2, 2021)

    [0.43.0] - 2021-11-02

    Added

    Fixed

    • Fix false positive with lambda argument and call chain (indent) (#1202)
    • Fix trailing spaces not formatted inside block comments (no-trailing-spaces) (#1197)
    • Do not check for .idea folder presence when using applyToIDEA globally (#1186)
    • Remove spaces before primary constructor (paren-spacing) (#1207)
    • Fix false positive for delegated properties with a lambda argument (indent) (#1210)
    • Remove unnecessary wildcard imports (no-unused-imports) (#1256)
    • Fix indentation of KDoc comment when using tab indentation style (indent) (#850)

    Changed

    • Support absolute paths for globs (#1131)
    • Fix regression from 0.41 with argument list wrapping after dot qualified expression (argument-list-wrapping)(#1159)
    • Update Gradle to 7.2 version
    • Update Gradle shadow plugin to 7.1 version
    • Update Kotlin version to 1.5.31 version. Default Kotlin API version was changed to 1.4!
    Source code(tar.gz)
    Source code(zip)
    ktlint(53.49 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.42.1(Aug 6, 2021)

  • 0.42.0(Jul 29, 2021)

    Thank you to the following contributors for this release:

    Added

    • SARIF output support (#1102)

    Fixed

    • Remove needless blank lines in dot qualified expression (#1077)
    • Fix false positives for SpacingBetweenDeclarationsWithAnnotationsRule (#1125)
    • Fix false positive with eol comment (annotation-spacing) (#1124)
    • Fix KtLint dependency variant selection (#1114)
    • Fix false positive with 'by lazy {}' (indent) (#1162)
    • Fix false positive with value argument list has lambda (indent) (#764)
    • Fix false positive in lambda in dot qualified expression (argument-list-wrapping) (#1112)
    • Fix false positive with multiline expression with elvis operator in assignment (indent) (#1165)
    • Ignore backticks in imports for ordering purposes (import-ordering) (#1106)
    • Fix false positive with elvis operator and comment (chain-wrapping) (#1055)
    • Fix false negative in when conditions (chain-wrapping) (#1130)
    • Fix the Html reporter Chinese garbled (#1140)
    • Performance regression introduced in 0.41.0 (#1135)

    Changed

    • Updated to dokka 1.4.32 (#1148)
    • Updated Kotlin to 1.5.20 version
    Source code(tar.gz)
    Source code(zip)
    ktlint(52.92 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.41.0(Mar 16, 2021)

    [0.41.0] - 2021-03-16

    Note: This release contains breaking changes to globs passed to ktlint via the command line. See (#999) and the README.

    Thank you to t-kameyama and paul-dingemans for your contributions to this release!

    Added

    • New ktlint_ignore_back_ticked_identifier EditorConfig option for max-line-length rule to ignore long method names inside backticks (primarily used in tests) (#1007)
    • Allow to add/replace loaded .editorconfig values via ExperimentalParams#editorConfigOverride (#1016)
    • ReporterProvider, LintError, RuleSetProvider now implement Serializable interface

    Fixed

    • Incorrect indentation with multiple interfaces (#1003)
    • Empty line before primary constructor is not reported and formatted-out (#1004)
    • Fix '.editorconfig' generation for "import-ordering" rule (#1011)
    • Fix "filename" rule will not work when '.editorconfig' file is not found (#997)
    • EditorConfig generation for import-ordering (#1011)
    • Internal error (no-unused-imports) (#996)
    • Fix false positive when argument list is after multiline dot-qualified expression (argument-list-wrapping) (#893)
    • Fix indentation for function types after a newline (indent) (#918)
    • Don't remove the equals sign for a default argument (no-line-break-before-assignment) (#1039)
    • Fix internal error in no-unused-imports (#1040)
    • Fix false positives when declaration has tail comments (spacing-between-declarations-with-comments) (#1053)
    • Fix false positive after else keyword (argument-list-wrapping) (#1047)
    • Fix formatting with comments (colon-spacing) (#1057)
    • Fix IndexOutOfBoundsException in argument-list-wrapping-rule formatting file with many corrections (#1081)
    • Fix formatting in arguments (multiline-if-else) (#1079)
    • Fix experimental:annotation-spacing-rule autocorrection with comments
    • Migrate from klob dependency and fix negated globs passed to CLI are no longer worked (#999) Breaking: absolute paths globs will no longer work, check updated README

    Changed

    • Update Gradle shadow plugin to 6.1.0 version
    • Align with Kotlin plugin on how alias pattern is represented for imports layout rule (#753)
    • Align with Kotlin plugin on how subpackages are represented (#753)
    • Deprecated custom kotlin_imports_layout EditorConfig property. Please use ij_kotlin_imports_layout to ensure that the Kotlin IDE plugin and ktlint use same imports layout (#753)
    • Deprecated idea and ascii shortcuts as the ij_kotlin_imports_layout property does not support those. Please check README on how to achieve those with patterns (#753)
    • Update Gradle to 6.8.3 version
    • Update Kotlin to 1.4.31 version. Fixes #1063.
    Source code(tar.gz)
    Source code(zip)
    ktlint(51.23 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.40.0(Dec 4, 2020)

    [0.40.0] - 2020-12-04

    Special thanks to t-kameyama for the huge number of bugfixes in this release!

    Added

    • Initial implementation IDE integration via '.editorconfig' based on rules default values (#701)
    • CLI subcommand generateEditorConfig to generate '.editorconfig' content for Kotlin files (#701)
    • A new capability to generate baseline and run ktlint against it with --baseline cli option (#707)

    Fixed

    • Do not report when semicolon is before annotation/comment/kdoc and lambda (#825)
    • Fix false positive when import directive has backticks and alias (#910)
    • @receiver annotations with parameters are not required to be on a separate line (#885)
    • Fix false positive "File annotations should be separated from file contents with a blank line" in kts files (#914)
    • Fix false positive Missing newline after "->" when when entry has a nested if/else block (#901)
    • Allow an inline block comment in argument-list-wrapping (#926)
    • Fix false positive for line-breaks inside lambdas in argument-list-wrapping (#861) (#870)
    • Fix wrong indentation inside an if-condition in argument-list-wrapping (#854) (#864)
    • Fix false positive for method after string template in argument-list-wrapping (#842) (#859)
    • Fix false positive when a comment is not between declarations in spacing-between-declarations-with-comments(#865)
    • Fix formatting with comments (multiline-if-else) (#944)
    • Do not insert unnecessary spacings inside multiline if-else condition (indent) (#871) (#900)
    • Correctly indent primary constructor parameters when class has multiline type parameter (parameter-list-wrapping) (#921) (#938)
    • Correctly indent property delegates (indent) (#939)
    • Fix false positive for semicolon between empty enum entry and member (no-semicolons) (#957)
    • Fix wrong indentation for class delegates (indent) (#960) (#963)
    • Fix wrong indentation in named arguments (indent) (#964)
    • Fix wrong indentation when a function has multiline type arguments (parameter-list-wrapping) (#965)
    • Fix false positive for spacing-between-declarations-with-annotations (#970)
    • Fix ParseException when an assigment contains comments (no-line-break-before-assignment) (#956)
    • Fix false positive when right brace is after a try-catch block (spacing-around-keyword) (#978)
    • Fix false positive for control flow with empty body (no-semicolons) (#955)
    • Fix incorrect indentation for multi-line call expressions in conditions (indent) (#959)
    • Fix false positive for trailing comma before right parentheses|bracket|angle (spacing-around-comma) (#975)
    • Fix ktlint CLI could skip checking some of explicetly passed files (#942)

    Changed

    • 'import-ordering' now supports `.editorconfig' default value generation (#701)
    • Update Gradle to 6.7.1 version
    Source code(tar.gz)
    Source code(zip)
    ktlint(47.22 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.39.0(Sep 14, 2020)

    Added

    • Add new applyToIDEA location for IDEA 2020.1.x and above on MacOs
    • Debug output: print loaded .editorconfig content
    • Extract argument-list-wrapping rule into experimental ruleset
    • Split annotation-spacing into separate experimental rule

    Fixed

    • Do not enforce raw strings opening quote to be on a separate line (#711)
    • False negative with multiline type parameter list in function signature for parameter-list-wrapping(#680)
    • Alternative .editorconfig path is ignored on stdin input (#869)
    • False positive with semicolons before annotations/comments/kdoc (#825)
    • Do not report when string-template expression is a keyword (#883)
    • False positive for subclass imports in no-unused-imports (#845)
    • False positive for static java function imports in no-unused-imports (#872)
    • Missing signature for KtLint CLI artifact published to Github release (#895)
    • Crash in annotation rule (#868)
    • False-positive unused import violation (#902)

    Changed

    • Ktlint object internal code cleanup
    • Deprecate some of public methods in Ktlint object that should not be exposed as public api
    • Update Kotlin to 1.4.10 version
    • Make RuleSet class open so it can be inherited
    Source code(tar.gz)
    Source code(zip)
    ktlint(51.65 MB)
    ktlint.asc(821 bytes)
    ktlint.asc.md5(32 bytes)
    ktlint.md5(32 bytes)
  • 0.38.1(Aug 27, 2020)

  • 0.38.0(Aug 21, 2020)

    New release with Kotlin 1.4.0 support and several enhancements and bugfixes.

    Added

    • Experimental SpacingAroundAngleBracketsRule (#769)
    • Checksum generation for executable Jar (#695)
    • Enable Gradle dependency verification
    • parameter-list-wrapping rule now also considers function arguments while wrapping (#620)
    • Publish snapshots built against kotlin development versions
    • Initial support for tab-based indentation (#128)

    Fixed

    • Safe-called wrapped trailing lambdas indented correctly (#776)
    • provideDelegate imports are not marked as unused anymore (#669)
    • Set continuation indent to 4 in IDE integration codestyle (#775)
    • No empty lines between annotation and annotated target (#688)
    • Unused imports reported correctly (#526) (#405)
    • No false empty lines inserted in multiline if-else block (#793)
    • No-wildcard-imports properly handles custom infix function with asterisk (#799)
    • Do not require else to be in the same line of a right brace if the right brace is not part of the if statement (#756)
    • Brace-less if-else bodies starting with parens indented correctly (#829)
    • If-condition with multiline call expression inside indented correctly (#796)

    Changed

    • Update Gradle to 6.6 version
    • Update ec4j to 0.2.2 version. Now it should report path to .editorconfig file on failed parsing and allow empty .editorconfig files.
    • Update Kotlin to 1.4.0 version (#830)
    Source code(tar.gz)
    Source code(zip)
    ktlint(51.62 MB)
    ktlint.asc(870 bytes)
    ktlint.md5(32 bytes)
  • 0.38.0-alpha01(Aug 18, 2020)

  • 0.37.2(Jun 16, 2020)

  • 0.37.1(Jun 8, 2020)

  • 0.37.0(Jun 3, 2020)

    Thank you to Tapchicoma and romtsn for all their hard work on this release!

    Added

    • Gradle wrapper validation (#684)
    • Experimental SpacingAroundDoubleColon rule (#722)
    • Experimental SpacingBetweenDeclarationsWithCommentsRule and SpacingBetweenDeclarationsWithAnnotationsRule. Fixes (#721)
    • kotlin_imports_layout config for .editorconfig file so that import ordering is configurable. Fixes (#527)

    Changed

    • Kotlin was updated to 1.3.70 version
    • Loading properties from .editorconfig was fully delegated to ec4j library. This fixes ability to override properties for specific files/directories (#742)
    • Promote experimental "indent" rule to standard one, old standard "indent" rule is removed
    • Functions to calculate line/column are now public so they can be used by 3rd party tools (#725)
    • AnnotationRule now handles file annotations as well (#714)

    Fixed

    • Ignore keywords in KDoc comments (#671)
    • Allow multiple spaces in KDoc comments (#706)
    • Trailing comment no longer reported as incorrect indentation (#710)
    • Annotated function types no longer reported as an error (#737)
    • FinalNewlineRule no longer reports error for empty files (#723)
    • EOL comments will no longer cause AnnotationRule to report an error (#736)
    • Formatter will no longer break class declaration with trailing comment (#728)
    • Formatting for single line if/else statements (#174)
    • Exception in NoLineBreakBeforeAssignmentRule (#693)

    Removed

    • Removed Maven; builds all run under Gradle (#445)
    • Old standard IndentRule
    Source code(tar.gz)
    Source code(zip)
    ktlint(49.55 MB)
    ktlint.asc(870 bytes)
  • 0.36.0(Dec 3, 2019)

    Added

    • HTML reporter (#641)
    • Experimental rule to lint enum entry names (#638)
    • @Suppress("RemoveCurlyBracesFromTemplate") now respected (#263)

    Upgraded

    • Gradle version to 5.6.2 (#616)
    • Kotlin to 1.3.60 (#658)

    Fixed

    • .git directory now discovered instead of hardcoded (#623)
    • Several bugs with the experimental annotation rule (#628) (#642) (#654) (#624)
    • Allow newline after lambda return type (#643)
    • Allow empty first line in a function that returns an anonymous object (#655)
    • Indentation with lambda argument (#627)
    • ktlint can now lint UTF-8 files with BOM (#630
    • Indentation with newline before return type (#663)
    • Build/tests on Windows (#640)
    • Allow whitespace after ( followed by a comment (#664)
    Source code(tar.gz)
    Source code(zip)
    ktlint(48.09 MB)
    ktlint.asc(870 bytes)
  • 0.35.0(Oct 13, 2019)

    Added

    • Support for specifying color for output via --color-name command line flag. (#585)
    • Support for custom rulesets and providers on Java 9+ (#573)

    Deprecated

    • --apply-to-idea flag; use applyToIDEA subcommand instead (#554)
    • --apply-to-idea-project flag; use applyToIDEAProject subcommand instead (#593)
    • 0.0.0-SNAPSHOT builds; snapshot builds are now versioned, e.g. 0.35.0-SNAPSHOT (#588)
      • Note: When using the new snapshot builds, you may need to add an explicit dependency on kotlin-compiler-embeddable to your ruleset project.

    Removed

    • Support for loading 3rd party rulesets via Maven (#566)

    Upgraded

    • Kotlin version to 1.3.50 (#565) (#611)

    Fixed

    • Bugs with spacing in experimental AnnotationRule (#552) (#601
    • Brackets would be removed from empty companion object (#600)
    • Bugs with experimental IndentationRule (#597) (#599)
    • Erroneous space between } and ] (#596)
    • Spacing around multiplication sign in lambdas (#598)
    • --version output with gradle-built JAR (#613)
    Source code(tar.gz)
    Source code(zip)
    ktlint(41.88 MB)
    ktlint.asc(870 bytes)
  • 0.34.2(Jul 23, 2019)

    Minor bugfix release for 0.34.0. (Note: 0.34.1 deprecated/deleted due to regression in disabled_flags .editorconfig support.)

    Added

    • Support for globally disabling rules via --disabled_rules command line flag. (#534)

    Fixed

    • Regression with --stdin flag for printAST command (#528)
    • Regressions with NoUnusedImports rule (#531, #526)
      • Note: this re-introduces #405
    • Indentation for enums with multi-line initializers (#518)
    Source code(tar.gz)
    Source code(zip)
    ktlint(45.06 MB)
    ktlint.asc(870 bytes)
  • 0.34.0(Jul 15, 2019)

    Added

    • Support for Kotlin 1.3.41
    • Support for globally disabling rules via custom disabled_rules property in .editorconfig (#503)
    • experimental:no-empty-first-line-in-method-block (#474)
    • Unit tests for ruleset providers

    Upgraded

    • AssertJ from 3.9.0 to 3.12.2 (#520)

    Enabled

    • Final newline by default (#446)
    • no-wildcard-import (Re-enabled after temporarily disabling in 0.33.0)
    • experimental:annotation (#509)
    • experimental:multiline-if-else (no autocorrection)
    • experimental:package-name (currently only disallows underscores in package names)

    Deprecated

    • MavenDependencyResolver. Scheduled to be removed in 0.35.0 ([#468])(https://github.com/pinterest/ktlint/pull/468)
    • --install-git-pre-commit-hook flag; use installGitPreCommitHook subcommand instead (#487)
    • --print-ast flag; use printAST subcommand instead (#500)

    Removed

    • Support for --ruleset-repository and --ruleset-update flags

    Fixed

    • import-ordering will now refuse to format import lists that contain top-level comments (#408)
    • no-unused-imports reporting false negatives or false positives in some cases (#405) and (#506)
    • experimental:indent incorrectly formatting a lambda's closing brace (#479)
    Source code(tar.gz)
    Source code(zip)
    ktlint(45.06 MB)
    ktlint.asc(870 bytes)
  • 0.33.0(May 28, 2019)

    Added

    • Support for Kotlin 1.3.31

    Disabled

    • No wildcard imports rule (#48). Developers wishing to still enforce this rule should add the code into a custom ruleset.

    Fixed

    • Spec file parsing is now platform-agnostic (#365)
    • Unnecessary newline after -> in some cases (#403)
    • SpacingAroundCommaRule will no longer move code into comments
    • Made newlines after = less aggressive (#368) (#380)
    • Erroneous newline when parameter comments are used (#433)
    Source code(tar.gz)
    Source code(zip)
    ktlint(40.64 MB)
    ktlint.asc(870 bytes)
  • 0.32.0(Apr 22, 2019)

    Note: This release will not be updated in the homebrew-ktlint tap; we will be opening a PR to make ktlint part of the core Homebrew formulae.

    Added

    • experimental/import-ordering rule (#189). Use ktlint --experimental to enabled.
    • Support for Kotlin 1.3.30
    • Build now compatible with jitpack

    Fixed

    • Incorrectly flagging a missing newline for functions with no parameters (#327).
    • Semicolons now allowed in KDocs (#362).
    • Spaces now disallowed after super (#369).
    • Annotations in function parameters now checked for indentation (#374]

    Changed

    • Code now lives in com.pinterest package
    • groupId now com.pinterest
    • Custom ruleset META-INF.services file must be renamed to com.pinterest.ktlint.core.RuleSetProvider
    Source code(tar.gz)
    Source code(zip)
    ktlint(40.60 MB)
    ktlint.asc(870 bytes)
  • 0.31.0-SNAPSHOT(Apr 16, 2019)

Owner
Pinterest
Pinterest's Open Source Projects
Pinterest
A quiz app built with trivia api. This app was built with mvvm architecture, dagger-hilt, retrofit, room database, and navigation components.

A quiz app built with trivia api. This app was built with mvvm architecture, dagger-hilt, retrofit, room database, and navigation components.

Stephen Odumirin 3 Dec 19, 2022
To Do List App is built in Kotlin using Material 3, Data Binding, Navigation Component Graphs, Room persistence library, Kotlin coroutines, LiveData, Dagger Hilt, and Notifications following MVVM Architecture.

ToDoListApp ToDoList App demonstrates modern Android development with Hilt, Coroutines, LiveData, Jetpack (Room, ViewModel), and Material 3 Design bas

Naman Garg 10 Jan 8, 2023
📒 NotyKT is a complete 💎Kotlin-stack (Backend + Android) 📱 application built to demonstrate the use of Modern development tools with best practices implementation🦸.

NotyKT ??️ NotyKT is the complete Kotlin-stack note taking ??️ application ?? built to demonstrate a use of Kotlin programming language in server-side

Shreyas Patil 1.4k Jan 8, 2023
Shreyas Patil 2.1k Dec 30, 2022
An android app built using Kotlin following Multi-Module Clean Architecture MVVM

Notflix ??️ Work In Progress ?? An android app built using Kotlin that consumes TMDB API to display current trending, upcoming and popular movies ?? a

Victor Kabata 290 Dec 30, 2022
Taskify - An app to manage your daily tasks and boost your productivity. Taskify is built using kotlin and follows all modern android Development practices and hence is a good learning resource for beginners

Taskify Taskify is an app to manage your daily tasks and boost your productivity Video Introduction ?? This is a small introduction video about Taskif

Vaibhav Jaiswal 101 Jan 4, 2023
The JeTrivia is built on a modern Android Development tech stack with MVVM architecture. Kotlin, Coroutine, Flow, StateFlow, Jetpack Compose, Navigation, Room, Hilt, Retrofit2, OkHttp3, kotlinx.serialization, MockK, Truth

JeTrivia ?? In Progress ?? The JeTrivia application is sample based on MVVM architecture. Fetching data from the network via repository pattern and sa

Tolga Bolatcan 5 Mar 31, 2022
Vaibhav Jaiswal 57 Jan 3, 2023
Wallum is a superfast ⚡ lightweight wallpaper app, built using Kotlin, Retrofit, MVVM, Paging 3, Hilt, and Navigation Components

Show some ❤️ and star the repo to show support for the project Wallum Android App Wallum is a super-fast ?? , lightweight wallpaper app built purely w

Aditya Verma 19 Dec 6, 2022
Android app which fetches a sample movies list to display. Built using Kotlin and latest Android tech stack, with an approach to clean architecture.

movies-sample-app This is an Android app which fetches a sample movies list to display. Built using Kotlin and latest Android tech stack, with an appr

Nadeem Ahmed 1 Oct 21, 2021
A Free, open source Contacts Butler App built with kotlin

Contacts Butler Do you have a bunch of contacts that are missing a lot of info such as names, emails, phone numbers, etc? Do you really know the conta

Android Contacts Butlers 1 Nov 30, 2021
A News App Built With Kotlin

NewsApp Retrofit Coroutines ViewModel Live Data Jetpack Navigation Room Database View Binding Data Binding Recycler View Splash Screen Pagination Onbo

Oğuzhan Türkmen 4 Jun 8, 2022
Weather App Built With Kotlin

WeatherApp In this project, I showed the user the nearby locations with the data I got from the GPS, and I made the details of the weather events of t

Ali Şamil Küçük 4 Jan 26, 2022
An android app built using Kotlin that consumes TMDB API to display current trending, upcoming and popular movies 🍿 .

Flick An android app built using Kotlin that consumes TMDB API to display current trending, upcoming and popular movies ?? .It has been built followin

Kagiri Charles 8 Nov 29, 2022
A Good Scanner Built With Kotlin

GoodScanner TODO OpenCV Android 프로젝트에 설치 https://webnautes.tistory.com/923 Gaussian Blurring 과 같은 기술을 이용하여 Image의 noise 제거 OpenCV를 이용한 Document Edge D

JoonBeom Park 3 Dec 21, 2021
Reddit App Built Using Kotlin

Reddit App Setup Build the project gets top post from reddit and displays different media(GIF.VIDEO,IMAGE). Enable user to add/remove a post to favour

Zalo Austine 0 Nov 17, 2021
An Android app built with Kotlin, to help students at Kibabii University make monthly class welfare contributions

An Android app built with Kotlin, to help students at Kibabii University make monthly class welfare contributions. It is built with the MVVM pattern and the latest Jetpack components. Firebase as the backend

Joel Kanyi 21 Sep 24, 2022
Foodies App Built With Kotlin

Foodies-App WhatsApp.Video.2021-11-26.at.2.17.56.AM.mp4 Foodies is an app for people who are binge eaters who can't control their hunger, but who are

Rifah A Khan 0 Dec 9, 2021
Movie List App Built With Kotlin

MovieList App Demo app that uses TheMovideDB V3 API to fetch some lists describing the upcoming, popular and top rated movies in their database. The u

Manvendra Pal 0 Dec 8, 2021