Skip to content

Commit

Permalink
Add the configuration property codeStyle
Browse files Browse the repository at this point in the history
  • Loading branch information
mfederczuk committed May 4, 2023
1 parent 00b3827 commit e05d0bb
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 44 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [**Semantic Versioning v2.0.0**](https://semver.org/

* The hook will now also print the configured ktlint version
* New `limit` configuration property for adding the `--limit=<limit>` flag to the ktlint invocation
* New `codeStyle` configuration property for adding the `--code-stye=<codeStyle>` flag to the ktlint invocation

### Deprecated ###

Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ ktlint {
version.set("0.49.0") // set the version of ktlint
// the following configuration properties are optional
android.set(true) // add the --android flag to ktlint
codeStyle.set(AndroidStudio) // add the --code-style=android_studio flag to ktlint
limit.set(5) // add the --limit=5 flag to ktlint
installGitPreCommitHookBeforeBuild.set(true) // automatically installs the hook every time before a build is started
}
Expand Down Expand Up @@ -105,7 +105,7 @@ ktlint {
version.set("0.49.0") // set the version of ktlint

// the following configuration properties are optional
android.set(true) // add the --android flag to ktlint
codeStyle.set(AndroidStudio) // add the --code-style=android_studio flag to ktlint
limit.set(5) // add the --limit=5 flag to ktlint
installGitPreCommitHookBeforeBuild.set(true) // automatically installs the hook every time before a build is started
}
Expand All @@ -130,7 +130,7 @@ ktlint {
version = '0.49.0' // set the version of ktlint
// the following configuration properties are optional
android = true // add the --android flag to ktlint
codeStyle = 'android_studio' // add the --code-style=android_studio flag to ktlint
limit = 5 // add the --limit=5 flag to ktlint
installGitPreCommitHookBeforeBuild = true // automatically installs the hook every time before a build is started
}
Expand Down Expand Up @@ -162,7 +162,7 @@ ktlint {
version = '0.49.0' // set the version of ktlint
// the following configuration properties are optional
android = true // add the --android flag to ktlint
codeStyle = 'android_studio' // add the --code-style=android_studio flag to ktlint
limit = 5 // add the --limit=5 flag to ktlint
installGitPreCommitHookBeforeBuild = true // automatically installs the hook every time before a build is started
}
Expand All @@ -175,7 +175,7 @@ ktlint {
## To-Do List ##

* [x] Configuration property to add the `--android` flag to `ktlint`
* [ ] Configuration property to add the `--code-style=<codeStyle>` flag to `ktlint`
* [x] Configuration property to add the `--code-style=<codeStyle>` flag to `ktlint`
* [ ] Automatically detecting Android projects and adding the `--android` / `--code-style=android_studio` flag if that
is the case
* [ ] Configuration property to add the `--disabled_rules=<disabledRules>` flag to `ktlint`
Expand Down
2 changes: 1 addition & 1 deletion demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repositories {

ktlint {
version.set("0.49.0")
// android.set(true)
// codeStyle.set(AndroidStudio)
// limit.set(5)
installGitPreCommitHookBeforeBuild.set(true)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.github.mfederczuk.gradle.plugin.ktlint

internal sealed class CodeStyle {

object Default : CodeStyle()

data class Specific(val name: String) : CodeStyle()
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ internal abstract class KtlintGitPreCommitHookInstallationTask : DefaultTask() {
@get:Input
abstract val taskName: Property<String>

@get:Input
abstract val codeStyle: Property<CodeStyle>

@get:Input
abstract val projectType: Property<ProjectType>

Expand All @@ -56,6 +59,7 @@ internal abstract class KtlintGitPreCommitHookInstallationTask : DefaultTask() {
fun installKtlintGitPreCommitHook() {
val ktlintClasspathJarFiles: Iterable<File> = this.ktlintClasspathJarFiles.get()
val taskName: String = this.taskName.get()
val codeStyle: CodeStyle = this.codeStyle.get()
val projectType: ProjectType = this.projectType.get()
val errorLimit: ErrorLimit = this.errorLimit.get()
val ktlintVersion: SemVer = this.ktlintVersion.get()
Expand All @@ -64,6 +68,7 @@ internal abstract class KtlintGitPreCommitHookInstallationTask : DefaultTask() {
.loadHookScript(
ktlintClasspathJarFiles.toList(),
taskName,
codeStyle,
projectType,
errorLimit,
ktlintVersion,
Expand All @@ -83,6 +88,7 @@ internal abstract class KtlintGitPreCommitHookInstallationTask : DefaultTask() {
private fun loadHookScript(
ktlintClasspathJarFiles: List<File>,
taskName: String,
codeStyle: CodeStyle,
projectType: ProjectType,
errorLimit: ErrorLimit,
ktlintVersion: SemVer,
Expand All @@ -100,13 +106,16 @@ internal abstract class KtlintGitPreCommitHookInstallationTask : DefaultTask() {

replace placeholder "HOOK_INSTALLATION_TASK_NAME" with taskName

replace placeholder "KTLINT_ANDROID_OPT_ARG" with when (projectType) {
ProjectType.OTHER -> ""
ProjectType.ANDROID -> {
if (ktlintVersion >= SemVer(0, 49, 0)) {
"--code-style=android_studio"
} else {
"--android"
replace placeholder "KTLINT_CODE_STYLE_OPT_ARG" with run {
if (ktlintVersion >= SemVer(0, 49, 0)) {
when (codeStyle) {
is CodeStyle.Default -> ""
is CodeStyle.Specific -> "--code-style=${codeStyle.name}"
}
} else {
when (projectType) {
ProjectType.OTHER -> ""
ProjectType.ANDROID -> "--android"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.gradle.api.Task
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ResolveException
import org.gradle.api.logging.Logger
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.provider.Provider
import org.gradle.kotlin.dsl.create
Expand All @@ -39,30 +40,7 @@ public class KtlintPlugin : Plugin<Project> {
override fun apply(project: Project) {
val extension: KtlintPluginExtension = this.createExtension(extensionContainer = project.extensions)

val ktlintVersionProvider: Provider<SemVer> = extension.version
.map<SemVer> { versionString: String ->
val requestedKtlintVersion: SemVer? = SemVer.parseOrNull(versionString)

if ((requestedKtlintVersion == null) && SemVer.isValid(versionString.removePrefix(prefix = "v"))) {
val msg: String =
"String \"$versionString\" is not a valid semantic version.\n" +
"Remove the leading 'v' character and " +
"use \"${versionString.removePrefix(prefix = "v")}\" instead"
error(msg)
}

checkNotNull(requestedKtlintVersion) {
"String \"$versionString\" is not not a valid semantic version.\n" +
"Ensure that the version was correctly copied from https://github.com/pinterest/ktlint/releases"
}

check(requestedKtlintVersion >= KTLINT_MIN_SUPPORTED_VERSION) {
"Configured ktlint version ($requestedKtlintVersion) is lower than " +
"minimum supported ktlint version $KTLINT_MIN_SUPPORTED_VERSION"
}

requestedKtlintVersion
}
val ktlintVersionProvider: Provider<SemVer> = extension.checkedKtlintVersion

val ktlintClasspathJarFilesProvider: Provider<Iterable<File>> = ktlintVersionProvider
.map<Iterable<File>> { version: SemVer ->
Expand Down Expand Up @@ -90,6 +68,7 @@ public class KtlintPlugin : Plugin<Project> {
this.registerGitPreCommitHookInstallationTask(
project,
ktlintClasspathJarFilesProvider,
codeStyleProvider = extension.codeStyleAsDistinctType,
projectTypeProvider,
errorLimitProvider,
ktlintVersionProvider,
Expand Down Expand Up @@ -133,6 +112,7 @@ public class KtlintPlugin : Plugin<Project> {
private fun registerGitPreCommitHookInstallationTask(
project: Project,
ktlintClasspathJarFilesProvider: Provider<Iterable<File>>,
codeStyleProvider: Provider<CodeStyle>,
projectTypeProvider: Provider<ProjectType>,
errorLimitProvider: Provider<ErrorLimit>,
ktlintVersionProvider: Provider<SemVer>,
Expand All @@ -143,6 +123,7 @@ public class KtlintPlugin : Plugin<Project> {

this@register.ktlintClasspathJarFiles.set(ktlintClasspathJarFilesProvider)
this@register.taskName.set(KTLINT_GIT_PRE_COMMIT_HOOK_INSTALLATION_TASK_NAME)
this@register.codeStyle.set(codeStyleProvider)
this@register.projectType.set(projectTypeProvider)
this@register.errorLimit.set(errorLimitProvider)
this@register.ktlintVersion.set(ktlintVersionProvider)
Expand All @@ -157,9 +138,52 @@ public class KtlintPlugin : Plugin<Project> {
"Extension of type ${KtlintPluginExtension::class.java.name} not found in $project".internalErrorMsg
}

this.checkCodeStyleProperties(logger = project.logger, extension)

this.setupAutomaticGitPreCommitHookInstallation(project, extension)
}

private fun checkCodeStyleProperties(logger: Logger, extension: KtlintPluginExtension) {
val ktlintVersion: SemVer = extension.checkedKtlintVersion.get()
val codeStyleProvider: Provider<CodeStyle> = extension.codeStyleAsDistinctType

if (ktlintVersion < SemVer(0, 49, 0)) {
when (codeStyleProvider.get()) {
is CodeStyle.Default -> Unit
is CodeStyle.Specific -> {
val msg: String =
"The property `codeStyle` is only available for ktlint version 0.49.0 and above.\n" +
"Either bump the configured ktlint version up or use the property `android` instead"
incompatibleConfiguration(msg)
}
}

return
}

val isAndroidProject: Boolean = extension.android.get()
if (!isAndroidProject) {
return
}

when (codeStyleProvider.get()) {
is CodeStyle.Default -> {
val msg: String =
"Since ktlint version 0.49.0 the --android flag is deprecated.\n" +
"Consider migrating to the --code-style flag. " +
"(Kotlin: `codeStyle.set(AndroidStudio)` / Groovy: `codeStyle = 'android_studio'`)"
logger.warn(msg)
}

is CodeStyle.Specific -> {
val msg: String =
"Both properties `codeStyle` and `android` are set.\n" +
"Use either one or none, but not both"
incompatibleConfiguration(msg)
}
}
}

private fun setupAutomaticGitPreCommitHookInstallation(project: Project, extension: KtlintPluginExtension) {
val installGitPreCommitHookBeforeBuild: Boolean = extension.installGitPreCommitHookBeforeBuild.get()
if (!installGitPreCommitHookBeforeBuild) {
Expand All @@ -185,4 +209,47 @@ public class KtlintPlugin : Plugin<Project> {
}

// endregion

// region extension extensions... yeah

private val KtlintPluginExtension.checkedKtlintVersion: Provider<SemVer>
get() {
return this@checkedKtlintVersion.version
.map<SemVer> { versionString: String ->
val requestedKtlintVersion: SemVer? = SemVer.parseOrNull(versionString)

if ((requestedKtlintVersion == null) && SemVer.isValid(versionString.removePrefix(prefix = "v"))) {
val msg: String =
"String \"$versionString\" is not a valid semantic version.\n" +
"Remove the leading 'v' character and " +
"use \"${versionString.removePrefix(prefix = "v")}\" instead"
error(msg)
}

checkNotNull(requestedKtlintVersion) {
"String \"$versionString\" is not not a valid semantic version.\n" +
"Ensure that the version was correctly copied from https://github.com/pinterest/ktlint/releases"
}

check(requestedKtlintVersion >= KTLINT_MIN_SUPPORTED_VERSION) {
"Configured ktlint version ($requestedKtlintVersion) is lower than " +
"minimum supported ktlint version $KTLINT_MIN_SUPPORTED_VERSION"
}

requestedKtlintVersion
}
}

private val KtlintPluginExtension.codeStyleAsDistinctType: Provider<CodeStyle>
get() {
return this@codeStyleAsDistinctType.codeStyle
.map<CodeStyle>(CodeStyle::Specific)
.orElse(CodeStyle.Default)
}

// endregion

private fun incompatibleConfiguration(msg: String): Nothing {
error("Incompatible configuration; $msg")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,63 @@ public interface KtlintPluginExtension {
* The version of ktlint to use.
*
* This property doesn't have a default value.
* A version must be explicitly set, otherwise attempting to run tasks will fail.
* A version must be explicitly set, otherwise configuration will fail.
*/
public val version: Property<String>

// region ktlint CLI flags

// region --code-style=<codeStyle>

/**
* Code style "`ktlint_official`".
*
* @see codeStyle
*/
@Suppress("PropertyName")
public val KtlintOfficial: String get() = "ktlint_official"

/**
* Code style "`intellij_idea`".
*
* @see codeStyle
*/
@Suppress("PropertyName")
public val IntellijIdea: String get() = "intellij_idea"

/**
* Code style "`android_studio`".
*
* @see codeStyle
*/
@Suppress("PropertyName")
public val AndroidStudio: String get() = "android_studio"

/**
*
* Adds the flag `--code-style=<codeStyle>` to the ktlint invocation.
*
* This property requires that the [version] property be set to `0.49.0` or above, otherwise configuration will
* fail.
*
* The default is no explicit code style / whatever ktlint uses as the default.
*
* @see KtlintOfficial
* @see IntellijIdea
* @see AndroidStudio
*/
public val codeStyle: Property<String>

// endregion

/**
* Whether or not this project is an android project.
*
* If set to `true`, prior to ktlint version `0.49.0`, then the flag `--android` will be added to the `ktlint`
* invocation. For ktlint version `0.49.0` and onwards, the flag `--code-style=android_studio` is added instead.
*
* This and the [codeStyle] property are mutually exclusive; If both are set, the configuration will fail.
*
* The default value is `false`.
*/
@Deprecated(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ readonly using_intellij_idea_terminal

#region running ktlint

ktlint_android_opt_arg=//KTLINT_ANDROID_OPT_ARG::quoted_string//
readonly ktlint_android_opt_arg
ktlint_code_style_opt_arg=//KTLINT_CODE_STYLE_OPT_ARG::quoted_string//
readonly ktlint_code_style_opt_arg

ktlint_relative_opt_arg='--relative'
if $using_intellij_idea_terminal; then
Expand All @@ -154,7 +154,7 @@ printf 'Running ktlint (v%s)...\n' "$ktlint_version" >&2

exc=0
java -classpath "$ktlint_classpath" "$ktlint_main_class_name" \
$ktlint_android_opt_arg \
$ktlint_code_style_opt_arg \
$ktlint_relative_opt_arg \
$ktlint_limit_opt_arg \
--patterns-from-stdin='' < "$staged_kotlin_filename_list_file_pathname" ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ readonly using_intellij_idea_terminal

#region running ktlint

ktlint_android_opt_arg=//KTLINT_ANDROID_OPT_ARG::quoted_string//
readonly ktlint_android_opt_arg
ktlint_code_style_opt_arg=//KTLINT_CODE_STYLE_OPT_ARG::quoted_string//
readonly ktlint_code_style_opt_arg

ktlint_relative_opt_arg='--relative'
if $using_intellij_idea_terminal; then
Expand All @@ -173,7 +173,7 @@ printf 'Running ktlint (v%s)...\n' "$ktlint_version" >&2

exc=0
java -classpath "$ktlint_classpath" "$ktlint_main_class_name" \
$ktlint_android_opt_arg \
$ktlint_code_style_opt_arg \
$ktlint_relative_opt_arg \
$ktlint_limit_opt_arg \
--patterns-from-stdin='' < "$staged_kotlin_filename_list_file_pathname" ||
Expand Down

0 comments on commit e05d0bb

Please sign in to comment.