Releases: pinterest/ktlint
1.0.0
💔 Breaking changes
-
Update and align Maven coordinates - #2195, by @paul-dingemans
Be sure to update Maven coordinates below, to get latest changes!Old Maven coordinates New Maven coordinates com.pinterest:ktlint com.pinterest.ktlint:ktlint-cli com.pinterest.ktlint:ktlint-reporter-baseline com.pinterest.ktlint:ktlint-cli-reporter-baseline com.pinterest.ktlint:ktlint-reporter-checkstyle com.pinterest.ktlint:ktlint-cli-reporter-checkstyle com.pinterest.ktlint:ktlint-cli-reporter com.pinterest.ktlint:ktlint-cli-reporter-core com.pinterest.ktlint:ktlint-reporter-format com.pinterest.ktlint:ktlint-cli-reporter-format com.pinterest.ktlint:ktlint-reporter-html com.pinterest.ktlint:ktlint-cli-reporter-html com.pinterest.ktlint:ktlint-reporter-json com.pinterest.ktlint:ktlint-cli-reporter-json com.pinterest.ktlint:ktlint-reporter-plain com.pinterest.ktlint:ktlint-cli-reporter-plain com.pinterest.ktlint:ktlint-reporter-plain-summary com.pinterest.ktlint:ktlint-cli-reporter-plain-summary com.pinterest.ktlint:ktlint-reporter-sarif com.pinterest.ktlint:ktlint-cli-reporter-sarif -
Add binary compatibility validator - #2131, by @mateuszkwiecinski
-
Replace kotlin public
data class
es with Poko compiler plugin generated ones - #2136, by @mateuszkwiecinski
As a part of public API stabilization, data classes are no longer used in the public API. As of that, functions likecopy()
orcomponentN()
(used for destructuring declarations) are not available anymore. -
Promote experimental rules - #2218, by @paul-dingemans
The rules below have been promoted to non-experimental rules:- blank-line-before-declaration
- context-receiver-wrapping
- discouraged-comment-location
- enum-wrapping
- function-naming
- function-signature
- if-else-bracing
- multiline-expression-wrapping
- if-else-wrapping
- no-blank-line-in-list
- no-consecutive-comments
- no-empty-file
- no-empty-first-line-in-class-body
- no-single-line-block-comment
- parameter-list-spacing
- property-naming
- statement-wrapping
- string-template-indent
- try-catch-finally-spacing
- type-argument-list-spacing
- type-parameter-list-spacing
- unnecessary-parentheses-before-trailing-lambda
-
Fix statement-wrapping and align rule classes - #2178, by @paul-dingemans
Rule classMultilineExpressionWrapping
has been renamed toMultilineExpressionWrappingRule
. Rule classStatementWrapping
has been renamed toStatementWrappingRule
.RULE_ID
constants below are moved to a different Java class at compile time. Each rule provided by Ktlint is to be accompanied by aRULE_ID
constant that can be used in theVisitorModifier.RunAfter
. Filenames did not comply with standard that it should end withRule
suffix.RULE ID Old Java class name New Java class name FUNCTION_EXPRESSION_BODY_RULE_ID
FunctionExpressionBodyKt FunctionExpressionBodyRuleKt FUNCTION_LITERAL_RULE_ID
FunctionLiteralKt FunctionLiteralRuleKt MULTILINE_EXPRESSION_WRAPPING_RULE_ID
MultilineExpressionWrappingKt MultilineExpressionWrappingRuleKt NO_BLANK_LINE_IN_LIST_RULE_ID
NoBlankLineInListKt NoBlankLineInListRuleKt NO_EMPTY_FILE_RULE_ID
(not applicable) NoEmptyFileRuleKt -
Update to Kotlin 1.9 & remove TreeCopyHandler extension - #2113, by @paul-dingemans
Classorg.jetbrains.kotlin.com.intellij.treeCopyHandler
is no longer registered as extension point for the compiler as this is not supported in Kotlin 1.9. Please test your custom rules. In case of unexpected exceptions during formatting of code, see #2044 for possible remediation.
🆕 Features
-
Change default code style to
ktlint_official
- #2144, by @paul-dingemans -
Add new experimental rule
class-signature
- #2119, by @paul-dingemans -
Add new experimental rule
function-expression-body
- #2151, by @paul-dingemans -
Add new experimental rule
chain-method-continuation
- #2088, by @atulgpt -
Add new experimental rule
function-literal
- #2137, by @paul-dingemans -
Add new experimental rule
function-type-modifier-spacing
rule - #2216, by @t-kameyama -
Define
EditorConfigOverride
for dynamically loaded ruleset - #2194, by @paul-dingemans
TheEditorConfigOverride
parameter of theKtlintRuleEngine
can be defined using the factory methodEditorConfigOverride.from(vararg properties: Pair<EditorConfigProperty<*>, *>)
. This requires theEditorConfigProperty
's to be available at compile time. Some commonEditorConfigProperty
's are defined inktlint-rule-engine-core
which is loaded as transitive dependency ofktlint-rule-engine
and as of that are available at compile.
If anEditorConfigProperty
is defined in aRule
that is only provided via a runtime dependency, it gets a bit more complicated. Thektlint-api-consumer
example has now been updated to show how theEditorConfigProperty
can be retrieved from theRule
. -
Move wrapping on semicolon from
wrapping
rule tostatement-wrapping
rule - #2222, by @paul-dingemans
🔧 Fixes
-
Do not indent class body for classes having a long super type list - #2116, by @paul-dingemans
-
Fix indent of explicit constructor - #2118, by @paul-dingemans
-
Fix incorrect formatting of nested function literal - #2107, by @paul-dingemans
-
Add property to disable ktlint for a glob in
.editorconfig
- #2108, by @paul-dingemans -
Fix spacing around colon in annotations - #2126, by @paul-dingemans
-
Fix solving problems in 3 consecutive runs - #2132, by @paul-dingemans
-
Fix indent parenthesized expression - #2127, by @paul-dingemans
-
Fix indent of IS_EXPRESSION, PREFIX_EXPRESSION and POSTFIX_EXPRESSION - #2125, by @paul-dingemans
-
Do not wrap a binary expression after an elvis operator - #2134, by @paul-dingemans
-
Drop obsolete class LintError in ktlint-api-consumer - #2145, by @paul-dingemans
-
Fix null pointer exception for if-else statement with empty THEN block - #2142, by @paul-dingemans
-
Fix false positive in propert...
0.50.0
Deprecation of ktlint-enable and ktlint-disable directives
The ktlint-disable
and ktlint-enable
directives are no longer supported. Ktlint rules can now only be suppressed using the @Suppress
or @SuppressWarnings
annotations. A new rule, internal:ktlint-suppression
, is provided to replace the directives with annotations.
API consumers do not need to provide this rule, but it does no harm when done.
The internal:ktlint-suppression
rule can not be disabled via the .editorconfig
nor via @Suppress
or @SuppressWarnings
annotations.
Custom Rule Providers need to prepare for Kotlin 1.9
In Kotlin 1.9 the extension points of the embedded kotlin compiler will change. Ktlint only uses the org.jetbrains.kotlin.com.intellij.treeCopyHandler
extension point. This extension is not yet supported in 1.9, neither is it documented (#KT-58704). Without this extension point it might happen that your custom rules will throw exceptions during runtime. See #1981.
In Ktlint, 7 out of 77 rules needed small and sometimes bigger changes to become independent of the extension point org.jetbrains.kotlin.com.intellij.treeCopyHandler
. The impact on your custom rules may vary dependent on the way the autocorrect has been implemented. When manipulating ASTNode
s there seems to be no impact. When, manipulating PsiElement
s, some functions consistently result in a runtime exception.
Based on the refactoring of the rules as provided by ktlint-ruleset-standard
in Ktlint 0.49.x
the suggested refactoring is as follows:
- Replace
LeafElement.replaceWithText(String)
withLeafElement.rawReplaceWithText(String)
. - Replace
PsiElement.addAfter(PsiElement, PsiElement)
withAstNode.addChild(AstNode, AstNode)
. Note that this method inserts the new node (first) argument before the second argument node and as of that is not a simple replacement of thePsiElement.addAfter(PsiElement, PsiElement)
. - Replace
PsiElement.replace(PsiElement)
with a sequence ofAstNode.addChild(AstNode, AstNode)
andAstNode.removeChild(AstNode)
.
Be aware that your custom rules might use other functions which also throw exceptions when the extension point org.jetbrains.kotlin.com.intellij.treeCopyHandler
is no longer supported.
In order to help you to analyse and fix the problems with your custom rules, ktlint temporarily supports to disable the extension point org.jetbrains.kotlin.com.intellij.treeCopyHandler
using a flag. This flag is available in the Ktlint CLI and in the KtlintRuleEngine
. By default, the extension point is enabled like it was in previous versions of ktlint.
At least you should analyse the problems by running your test suits by running ktlint and disabling the extension point. Next you can start with fixing and releasing the updated rules. All rules in this version of ktlint have already been refactored and are not dependent on the extension point anymore. In Ktlint CLI the flag is to be activated with parameter --disable-kotlin-extension-point
. API Consumers that use the KtlintRuleEngine
directly, have to set property enableKotlinCompilerExtensionPoint
to false
.
At this point in time, it is not yet decided what the next steps will be. Ktlint might drop the support of the extension points entirely. Or, if the extension point org.jetbrains.kotlin.com.intellij.treeCopyHandler
is fully supported at the time that ktlint will be based on kotlin 1.9 it might be kept. In either case, the flag will be dropped in a next version of ktlint.
Added
- Add new experimental rule
binary-expression-wrapping
. This rule wraps a binary expression in case the max line length is exceeded (#1940) - Add flag to disable extension point
org.jetbrains.kotlin.com.intellij.treeCopyHandler
to analyse impact on custom rules #1981 - Add new experimental rule
no-empty-file
for all code styles. A kotlin (script) file may not be empty (#1074) - Add new experimental rule
statement-wrapping
which ensures function, class, or other blocks statement body doesn't start or end at starting or ending braces of the block (#1938) - Add new experimental rule
blank-line-before-declaration
. This rule requires a blank line before class, function or property declarations (#1939) - Wrap multiple statements on same line
wrapping
(#1078) - Add new rule
ktlint-suppression
to replace thektlint-disable
andktlint-enable
directives with annotations. This rule can not be disabled via the.editorconfig
(#1947) - Inform user about using
--format
option of KtLint CLI when finding a violation that can be autocorrected (#1071)
Removed
- Code which was deprecated in
0.49.x
is removed. Consult changelog of 0.49.x` released for more information. Summary of removed code:
Fixed
- Do not flag a (potential) mutable extension property in case the getter is annotated or prefixed with a modifier
property-naming
(#2024) - Do not merge an annotated expression body with the function signature even if it fits on a single line (#2043)
- Ignore property with name
serialVersionUID
inproperty-naming
(#2045) - Prevent incorrect reporting of violations in case a nullable function type reference exceeds the maximum line length
parameter-list-wrapping
(#1324) - Prevent false negative on
else
branch when body contains only chained calls or binary expression (#2057) - Fix indent when property value is wrapped to next line (#2095)
Changed
- Fix Java interoperability issues with
RuleId
andRuleSetId
classes. Those classes were defined as value classes in0.49.0
and0.49.1
. Although the classes were marked with@JvmInline
it seems that it is not possible to uses those classes from Java base API Consumers like Spotless. The classes have now been replaced with data classes (#2041) - Update dependency
info.picocli:picocli
to v4.7.4 - Update dependency
org.junit.jupiter:junit-jupiter
to v5.9.3 - Update Kotlin development version to
1.8.22
and Kotlin version to1.8.22
. - Update dependency io.github.detekt.sarif4k:sarif4k to v0.4.0
- Update dependency org.jetbrains.dokka:dokka-gradle-plugin to v1.8.20
- Run format up to 3 times in case formatting introduces changes which also can be autocorrected (#2084)
0.49.1
Added
Removed
Fixed
- Store path of file containing a lint violation relative to the location of the baseline file itself (#1962)
- Print absolute path of file in lint violations when flag "--relative" is not specified in Ktlint CLI (#1963)
- Handle parameter
--code-style=android_studio
in Ktlint CLI identical to deprecated parameter--android
(#1982) - Prevent nullpointer exception (NPE) if class without body is followed by multiple blank lines until end of file
no-consecutive-blank-lines
(#1987) - Allow to 'unset' the
.editorconfig
propertyktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than
when usingktlint_official
code stylefunction-signature
(#1977) - Prevent nullpointer exception (NPE) if or operator at start of line is followed by dot qualified expression
indent
(#1993) - Fix indentation of multiline parameter list in function literal
indent
(#1976) - Restrict indentation of closing quotes to
ktlint_official
code style to keep formatting of other code styles consistent with0.48.x
and beforeindent
(#1971) - Extract rule
no-single-line-block-comment
fromcomment-wrapping
rule. Theno-single-line-block-comment
rule is added as experimental rule to thektlint_official
code style, but it can be enabled explicitly for the other code styles as well. (#1980) - Clean-up unwanted logging dependencies (#1998)
- Fix directory traversal for patterns referring to paths outside of current working directory or any of it child directories (#2002)
Changed
- Moved class
Baseline
fromktlint-cli
toktlint-cli-reporter-baseline
so that Baseline functionality is reusable for API Consumers.
0.49.0
WARNING: This version of KtLint contains a number of breaking changes in KtLint CLI and KtLint API. If you are using KtLint with custom ruleset jars or custom reporter jars, then those need to be upgraded before you can use them with this version of ktlint. Please contact the maintainers of those jars and ask them to upgrade a.s.a.p.
All rule id's in the output of Ktlint are now prefixed with a rule set. Although KtLint currently supports standard rules to be unqualified, users are encouraged to include the rule set id in all references to rules. This includes following:
- The
--disabled-rules
parameter in KtLint CLI. - The
.editorconfig
properties used to enable or disable rule and rule sets. Note that propertiesdisabled_rules
andktlint_disabled_rules
have been removed in this release. See disabled rules for more information. - The
source
element in the KtLint CLIbaseline.xml
file. Regenerating this file, fixes all rule references automatically. - The KtLint disable directives
ktlint-enable
/ktlint-disable
and the@Suppress('ktlint:...')
annotations. - The
VisitorModifier.RunAfterRule
.
Moving experimental rules to standard rule set
The experimental
rule set has been merged with standard
rule set. The rules which formerly were part of the experimental
rule set are still being treated as before. The rules will only be run in case .editorconfig
property ktlint_experimental
is enabled or in case the rule is explicitly enabled.
Note that the prefix experimental:
has to be removed from all references to this rule. Check references in:
- The
--disabled-rules
parameter in KtLint CLI. - The
.editorconfig
properties used to enable or disable rule and rule sets. Note that propertiesdisabled_rules
andktlint_disabled_rules
have been removed in this release. See disabled rules for more information. - The KtLint disable directives
ktlint-enable
/ktlint-disable
and the@Suppress('ktlint:...')
annotations. - The
VisitorModifier.RunAfterRule
.
Promote experimental rules to non-experimental
The rules below have been promoted to non-experimental rules:
- block-comment-initial-star-alignment
- class-naming
- comment-wrapping
- function-return-type-spacing
- function-start-of-body-spacing
- function-type-reference-spacing
- fun-keyword-spacing
- kdoc-wrapping
- modifier-list-spacing
- nullable-type-spacing
- spacing-between-function-name-and-opening-parenthesis
- unnecessary-parentheses-before-trailing-lambda
Note that this only affects users that have enabled the standard ruleset while having the experimental rules disabled.
API Changes & RuleSet providers & Reporter Providers
This release is intended to be the last release before the 1.0.x release of ktlint. If all goes as planned, the 1.0.x release does not contain any new breaking changes with except of removal of functionality which is deprecated in this release.
This release contains a lot of breaking changes which aims to improve the future maintainability of Ktlint. If you get stuck while migrating, please reach out to us by creating an issue.
Experimental rules
Rules in custom rule sets can now be marked as experimental by implementing the Rule.Experimental
interface on the rule. Rules marked with this interface will only be executed by Ktlint if .editorconfig
property ktlint_experimental
is enabled or if the rule itself has been enabled explicitly.
When using this feature, experimental rules should not be defined in a separate rule set as that would require a distinct rule set id. When moving a rule from an experimental rule set to a non-experimental rule set this would mean that the qualified rule id changes. For users of such rules this means that ktlint directives to suppress the rule and properties in the .editorconfig
files have to be changed.
EditorConfig
Field defaultAndroidValue
in class EditorConfigProperty
has been renamed to androidStudioCodeStyleDefaultValue
. New fields ktlintOfficialCodeStyleDefaultValue
and intellijIdeaCodeStyleDefaultValue
have been added. Read more about this in the section "Ktlint Official code style".
The .editorconfig
properties disabled_rules
and ktlint_disabled_rules
are no longer supported. Specifying those properties in the editorConfigOverride
or editorConfigDefaults
result in warnings at runtime.
'Ktlint Official` code style and renaming of existing code styles
A new code style ktlint_official
is introduced. This code style is work in progress but will become the default code style in the 1.0
release. Please try out the new code style and provide your feedback via the issue tracker.
This ktlint_official
code style combines the best elements from the Kotlin Coding conventions and Android's Kotlin styleguide. This code style also provides additional formatting on topics which are not (explicitly) mentioned in those conventions and style guide. But do note that this code style sometimes formats code in a way which is not accepted by the default code formatters in IntelliJ IDEA and Android Studio. The formatters of those editors produce nicely formatted code in the vast majority of cases. But in a number of edge cases, the formatting contains bugs which are waiting to be fixed for several years. The new code style formats code in a way which is compatible with the default formatting of the editors whenever possible. When using this codestyle, it is best to disable (e.g. not use) code formatting in the editor.
The existing code styles have been renamed to make more clear what the basis of the code style is.
The official
code style has been renamed to intellij_idea
. Code formatted with this code style aims to be compatible with default formatter of IntelliJ IDEA. This code style is based on Kotlin Coding conventions. If .editorconfig
property ktlint_code_style
has been set to android
then do not forget to change the value of that property to intellij_idea
. When not set, this is still the default code style of ktlint 0.49
. Note that the default code style will be changed to ktlint_official
in the 1.0
release.
Code style android
has been renamed to android_studio
. Code formatted with this code style aims to be compatible with default formatter of Android Studio. This code style is based on Android's Kotlin styleguide. If .editorconfig
property ktlint_code_style
has been set to android
then do not forget to change the value of that property to android_studio
.
Package restructuring and class relocation
The internal structure of the Ktlint project has been revised. The Ktlint CLI and KtLint API modules have been decoupled where possible. Modules have been restructured and renamed. See API Overview for more information.
This is the last release that contains module ktlint-core
as it had too many responsibilities. All classes in this module are relocated to other modules. Some classes have also been renamed. See tables below for details. Classes that are left behind in the ktlint-core
module are deprecated and were kept in this version for backwards compatibility only. The ktlint-core
module will be removed in Ktlint 0.50.x
.
Classes below have been moved from module ktlint-core
to the new module ktlint-rule-engine-core
:
Old class/package name in ktlint-core |
New class/package name in ktlint-rule-engine-core |
---|---|
com.pinterest.ktlint.core.api.editorconfig | com.pinterest.ktlint.rule.engine.core.api.editorconfig |
com.pinterest.ktlint.core.api.EditorConfigProperties | com.pinterest.ktlint.rule.engine.core.api.EditorConfig |
com.pinterest.ktlint.core.api.OptInFeatures | com.pinterest.ktlint.rule.engine.core.api.OptInFeatures |
com.pinterest.ktlint.core.ast.ElementType | com.pinterest.ktlint.rule.engine.core.api.ElementType |
com.pinterest.ktlint.core.ast.package | com.pinterest.ktlint.rule.engine.core.api.ASTNodeExtension |
com.pinterest.ktlint.core.IndentConfig | com.pinterest.ktlint.rule.engine.core.api.IndentConfig |
com.pinterest.ktlint.core.Rule ... |
0.48.2
Additional clarification on API Changes in 0.48.0
and 0.48.1
Starting with Ktlint 0.48.x
, rule and rule sets can be enabled/disabled with a separate property per rule (set). Please read deprecation of (ktlint_)disable_rules property for more information.
API Consumers that provide experimental rules to the KtLintRuleEngine, must also enable the experimental rules or instruct their users to do so in the .editorconfig
file. From the perspective of the API Consumer it might be confusing or unnecessary to do so as the experimental rule was already provided explicitly.
Ktlint wants to provide the user (e.g. a developer) a uniform and consistent user experience. The .editorconfig
becomes more and more central to store configuration for Ktlint. This to ensure that all team members use the exact same configuration when running ktlint regardless whether the Ktlint CLI or an API Consumer is being used.
The .editorconfig
is a powerful configuration tool which can be used in very different ways. Most projects use a single .editorconfig
file containing one common section for kotlin and kotlin scripts files. For example, the .editorconfig
file of the Ktlint project contains following section:
[*.{kt,kts}]
ij_kotlin_imports_layout = *
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true
Other projects might contain multiple .editorconfig
files for different parts of the project directory hierarchy. Or, use a single .editorconfig
file containing multiple sections with different globs. Like all other configuration settings in Ktlint, the user should be able to enable and disable the experimental rules. Both for the entire set of experimental rules and for individual experimental rules.
Ktlint allows API Consumers to set default values and override values for the .editorconfig
. Specifying a default value means that the user does not need to define the property in the .editorconfig
file but if the user specifies the value, it will take precedence. Specifying the override value ensures that this takes precedence on a value specified by the user in the .editorconfig
.
From the Ktlint perspective, it is advised that API Consumers provide the default value. See example below, for how to specify the editorConfigDefault
property:
KtLintRuleEngine(
ruleProviders = ruleProviders,
editorConfigDefaults = EditorConfigDefaults(
EditorConfig
.builder()
.section(
Section
.builder()
.glob(Glob("*.{kt,kts}"))
.properties(
Property
.builder()
.name("ktlint_experimental")
.value("enabled"),
),
)
.build()
)
)
If the user has set property ktlint_experimental
explicitly than that value will be used. If the value is not defined, the value provided via editorConfigDefaults
will be used.
If you do want to ignore the value of ktlint_experimental
as set by the user, than you can set the EditorConfigOverride property. But as said before that is discouraged as the user might not understand why the .editorconfig
property is being ignored (provided that the value set is not equal to the value provided by the API Consumer).
Added
Removed
Fixed
- Fix with array-syntax annotations on the same line as other annotations
annotation
(#1765) - Do not enable the experimental rules by default when
.editorconfig
propertiesdisabled_rules
orktlint_disabled_rules
are set. (#1771) - A function signature not having any parameters which exceeds the
max-line-length
should be ignored by rulefunction-signature
(#1773) - Allow diacritics in names of classes, functions packages, and properties
class-naming
,function-naming
,package-name
,property-naming
(#1757) - Prevent violation of
file-name
rule on code snippets (#1768) - Clarify that API Consumers have to enable experimental rules (#1768)
- Trim spaces in the
.editorconfig
propertyij_kotlin_imports_layout
's entries (#1770)
Changed
0.48.1
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 to1.8.0
.
0.48.0
[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 withcom.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty
. - Class
com.pinterest.ktlint.core.KtLintParseException
has been replaced withcom.pinterest.ktlint.core.api.KtLintParseException
. - Class
com.pinterest.ktlint.core.RuleExecutionException
has been replaced withcom.pinterest.ktlint.core.api.KtLintRuleException
. - Class
com.pinterest.ktlint.reporter.format.internal.Color
has been moved tocom.pinterest.ktlint.reporter.format.Color
. - Class
com.pinterest.ktlint.reporter.plain.internal.Color
has been moved tocom.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 .editorconfig
s
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 rulecontext-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 exposededitorConfigProperties
(#1671) - Do not add a second trailing comma, if the original trailing comma is followed by a KDOC
trailing-comma-on-declaration-site
andtrailing-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 to1.7.21
. - The default value for trailing comma's on call site is changed to
true
unless theandroid 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 theandroid 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 imp...
0.47.1
[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)
0.47.0
[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 withstatus
(typeBaseline.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 w...
0.46.1
[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)