-
Notifications
You must be signed in to change notification settings - Fork 508
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Clarify how to implement an API Consumer (#1881)
- Loading branch information
1 parent
1b66f18
commit 8757eb6
Showing
8 changed files
with
235 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# Custom integration | ||
|
||
!!! warning | ||
This page is based on Ktlint `0.49.x` which has to be released. Most concepts are also applicable for `0.48.x`. | ||
|
||
## Ktlint Rule Engine | ||
|
||
The `Ktlint Rule Engine` is the central entry point for custom integrations with the `Ktlint API`. See [basic API Consumer](https://github.com/pinterest/ktlint/blob/master/ktlint-api-consumer/src/main/kotlin/com/example/ktlint/api/consumer/KtlintApiConsumer.kt) for a basic example on how to invoke the `Ktlint Rule Engine`. This example also explains how the logging of the `Ktlint Rule Engine` can be configured to your needs. | ||
|
||
The `KtLintRuleEngine` instance only needs to be created once for the entire lifetime of your application. Reusing the same instance results in better performance due to caching. | ||
|
||
```kotlin title="Creating the KtLintRuleEngine" | ||
val ktLintRuleEngine = | ||
KtLintRuleEngine( | ||
ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS, | ||
) | ||
``` | ||
|
||
### Rule provider | ||
|
||
The `KtLintRuleEngine` must be configured with at least one `RuleProvider`. A `RuleProvider` is a lambda which upon request of the `KtLintRuleEngine` provides a new instance of a specific rule. You can either provide any of the standard rules provided by KtLint or with your own custom rules, or with a combination of both. | ||
```kotlin title="Creating a set of RuleProviders" | ||
val KTLINT_API_CONSUMER_RULE_PROVIDERS = | ||
setOf( | ||
// Can provide custom rules | ||
RuleProvider { NoVarRule() }, | ||
// but also reuse rules from KtLint rulesets | ||
RuleProvider { IndentationRule() }, | ||
) | ||
``` | ||
|
||
### Editor config: defaults & overrides | ||
|
||
When linting and formatting files, the `KtlintRuleEngine` takes the `.editorconfig` file(s) into account which are found on the path to the file. A property which is specified in the `editorConfigOverride` property of the `KtLintRuleEngine` takes precedence above the value of that same property in the `.editorconfig` file. The `editorConfigDefaults` property of the `KtLintRuleEngine` can be used to specify the fallback values for properties in case that property is not defined in the `.editorconfig` file (or in the `editorConfigOverride` property). | ||
|
||
```kotlin title="Specifying the editorConfigOverride" | ||
val ktLintRuleEngine = | ||
KtLintRuleEngine( | ||
ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS, | ||
editorConfigOverride = EditorConfigOverride.from( | ||
INDENT_STYLE_PROPERTY to IndentConfig.IndentStyle.SPACE, | ||
INDENT_SIZE_PROPERTY to 4 | ||
) | ||
) | ||
``` | ||
|
||
The `editorConfigOverride` property takes an `EditorConfigProperty` as key. KtLint defines several such properties, but they can also be defined as part of a custom rule. | ||
|
||
The `editorConfigDefaults` property is more cumbersome to define as it is based directly on the data format of the `ec4j` library which is used for parsing the `.editorconfig` file. | ||
|
||
The defaults can be loaded from a path or a directory. If a path to a file is specified, the name of the file does not necessarily have to end with `.editorconfig`. If a path to a directory is specified, the directory should contain a file with name `.editorconfig`. Note that the `propertyTypes` have to be derived from the same collection of rule providers that are specified in the `ruleProviders` property of the `KtLintRuleEngine`. | ||
|
||
```kotlin title="Specifying the editorConfigDefaults using an '.editorconfig' file" | ||
val ktLintRuleEngine = | ||
KtLintRuleEngine( | ||
ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS, | ||
editorConfigDefaults = EditorConfigDefaults.load( | ||
path = Paths.get("/some/path/to/editorconfig/file/or/directory"), | ||
propertyTypes = KTLINT_API_CONSUMER_RULE_PROVIDERS.propertyTypes(), | ||
) | ||
) | ||
``` | ||
If you want to include all RuleProviders of the Ktlint project than you can easily retrieve the collection using `StandardRuleSetProvider().getRuleProviders()`. | ||
|
||
The `EditorConfigDefaults` property can also be specified programmatically as is shown below: | ||
|
||
```kotlin title="Specifying the editorConfigDefaults programmatically" | ||
val ktLintRuleEngine = | ||
KtLintRuleEngine( | ||
ruleProviders = KTLINT_API_CONSUMER_RULE_PROVIDERS, | ||
editorConfigDefaults = EditorConfigDefaults( | ||
org.ec4j.core.model.EditorConfig | ||
.builder() | ||
// .. add relevant properties | ||
.build() | ||
) | ||
) | ||
``` | ||
|
||
### Lint & format | ||
|
||
Once the `KtLintRuleEngine` has been defined, it is ready to be invoked for each file or code snippet that has to be linted or formatted. The the `lint` and `format` functions take a `Code` instance as parameter. Such an instance can either be created from a file | ||
```kotlin title="Code from file" | ||
val code = Code.fromFile( | ||
File("/some/path/to/file") | ||
) | ||
``` | ||
or a code snippet (set `script` to `true` to handle the snippet as Kotlin script): | ||
```kotlin title="Code from snippet" | ||
val code = Code.fromSnippet( | ||
""" | ||
val code = "some-code" | ||
""".trimIndent() | ||
) | ||
``` | ||
|
||
The `lint` function is invoked with a lambda which is called each time a `LintError` is found and does not return a result. | ||
```kotlin title="Specifying the editorConfigDefaults programmatically" | ||
ktLintRuleEngine | ||
.lint(codeFile) { lintError -> | ||
// handle | ||
} | ||
``` | ||
|
||
The `format` function is invoked with a lambda which is called each time a `LintError` is found and returns the formatted code as result. Note that the `LintError` should be inspected for errors that could not be autocorrected. | ||
```kotlin title="Specifying the editorConfigDefaults programmatically" | ||
val formattedCode = | ||
ktLintRuleEngine | ||
.format(codeFile) { lintError -> | ||
// handle | ||
} | ||
``` | ||
|
||
## Logging | ||
|
||
Ktlint uses the `io.github.microutils:kotlin-logging` which is a `slf4j` wrapper. As API consumer you can choose which logging framework you want to use and configure that framework to your exact needs. The [basic API Consumer](https://github.com/pinterest/ktlint/blob/master/ktlint-api-consumer/src/main/kotlin/com/example/ktlint/api/consumer/KtlintApiConsumer.kt) contains an example with `org.slf4j:slf4j-simple` as logging provider and a customized configuration which shows logging at `DEBUG` level for all classes except one specific class which only displays logging at `WARN` level. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Ktlint API Consumer | ||
|
||
This module contains a very basic example of how to implement an API Consumer on top of the Ktlint API. If you want to implement your own custom API Consumer than you can copy this module into a stand-alone project or as submodule into another project. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 0 additions & 15 deletions
15
ktlint-api-consumer/src/main/kotlin/com/example/ktlint/api/consumer/Main.kt
This file was deleted.
Oops, something went wrong.
40 changes: 40 additions & 0 deletions
40
ktlint-api-consumer/src/main/resources/simplelogger.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# SLF4J's SimpleLogger configuration file | ||
|
||
# This file contains the configuration for the logging framework which is added as dependency of the module (see build.gradle.kts). When you | ||
# use another framework than "slf4j-simple", the configuration below will not work. Check out the documentation of the chosen framework how | ||
# it should be configured. Most likely, it has comparable capabilities. | ||
|
||
# Default logging detail level for all instances of SimpleLogger. | ||
# Must be one of ("trace", "debug", "info", "warn", or "error"). | ||
# If not specified, defaults to "info". | ||
#org.slf4j.simpleLogger.defaultLogLevel=warn | ||
|
||
# Logging detail level which can either be set for a specific class or all classes in a specific package. If your project already contains | ||
# a logger, you might want to set the logging for ktlint classes only. | ||
# | ||
# Must be one of ("trace", "debug", "info", "warn", or "error"). | ||
# If not specified, the default logging detail level is used. Specifying another loglevel (for example the value "off") results in | ||
# suppressing all logging for the class or package. Although this can be abused to suppress all logging from KtLint, you are advised no to | ||
# do this. It is better to set the loglevel to "debug" to reduce all logging except the error messages that you don't want to miss. | ||
org.slf4j.simpleLogger.log.com.pinterest.ktlint=debug | ||
# Additional logging detail levels can be set. Although rule above suppresses all log messages at levels warn, info, debug and trace, the | ||
# line below adds an exception for a specific class which might be relevant for you. | ||
org.slf4j.simpleLogger.log.com.pinterest.ktlint.rule.engine.internal.EditorConfigDefaultsLoader=warn | ||
|
||
# Set to true if you want the current date and time to be included in output messages. | ||
# Default is false, and will output the number of milliseconds elapsed since startup. | ||
#org.slf4j.simpleLogger.showDateTime=false | ||
|
||
# The date and time format to be used in the output messages. | ||
# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat. | ||
# If the format is not specified or is invalid, the default format is used. | ||
# The default format is yyyy-MM-dd HH:mm:ss:SSS Z. | ||
#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z | ||
|
||
# Set to true if you want to output the current thread name. | ||
# Defaults to true. | ||
#org.slf4j.simpleLogger.showThreadName=true | ||
|
||
# Set to true if you want the Logger instance name to be included in output messages. | ||
# Defaults to true. | ||
#org.slf4j.simpleLogger.showLogName=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters