Skip to content

Commit

Permalink
add lint and format tasks to android projects (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremymailen authored May 30, 2017
1 parent 25334f0 commit a0dbd2b
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 25 deletions.
31 changes: 18 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,46 @@ Available on the Gradle Plugins Portal: https://plugins.gradle.org/plugin/org.jm

```groovy
plugins {
id 'org.jmailen.kotlinter' version '0.8.1'
id 'org.jmailen.kotlinter' version '0.9.0'
}
```

### Features
- Linting and formatting tasks
- Extends Kotlin JVM and Android projects with lint and format tasks for each `SourceSet`
- Standalone `LintTask` and `FormatTask` types for defining custom tasks
- Incremental build support
- `.kt` and `.kts` source support
- Report and console outputs

### Tasks

If your project uses the JetBrains Kotlin JVM Gradle plugin, standard tasks will created:
If your project uses the JetBrains Kotlin JVM or Android Gradle plugins, standard tasks are created:

`formatKotlin`: format Kotlin source code according to `ktlint` rules (when possible to auto-format).
`formatKotlin`: format Kotlin source code according to `ktlint` rules or warn when auto-format not possible.

`lintKotlin`: check Kotlin source code for lint formatting error and (by default) fail the build.
`lintKotlin`: report Kotlin lint errors and by default fail the build.

Additionally the `check` task becomes dependent on `lintKotlin`.
Also `check` becomes dependent on `lintKotlin`.

Granular tasks also exist for each source set in the project: `formatKotlin`*`SourceSet`* and `lintKotlin`*`SourceSet`*.
Granular tasks exist for each source set in the project: `formatKotlin`*`SourceSet`* and `lintKotlin`*`SourceSet`*.

If you haven't applied the Kotlin JVM plugin you can still create custom tasks:
### Custom Tasks

If you haven't applied these plugins you can create custom tasks:

```groovy
import org.jmailen.gradle.kotlinter.tasks.LintTask
import org.jmailen.gradle.kotlinter.tasks.FormatTask
task ktLint(type: LintTask, group: 'verification') {
source files('src/kotlin')
report = file('build/lint-report.txt')
}
task ktFormat(type: FormatTask, group: 'formatting') {
source files('src/kotlin')
report = file('build/format-report.txt')
}
```

### Configuration
Expand All @@ -65,11 +74,7 @@ If you need to use a different version of `ktlint` you can override the dependen
```groovy
buildscript {
configurations.classpath {
resolutionStrategy { force 'com.github.shyiko:ktlint:0.6.1' }
resolutionStrategy { force 'com.github.shyiko:ktlint:0.7.1' }
}
}
```

### Planned Features
- dependency configuration for adding ktlint [rulesets](https://github.com/shyiko/ktlint#creating-a-ruleset)
- additional configurability along the lines of [checkstyle](https://docs.gradle.org/current/userguide/checkstyle_plugin.html)
7 changes: 6 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ plugins {

repositories {
jcenter()
maven { url 'https://maven.google.com' }
}

dependencies {
compile 'com.github.shyiko:ktlint:0.6.2'
compileOnly 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.2-2'
compileOnly 'com.android.tools.build:gradle:2.3.2'
testCompile 'junit:junit:4.12'
testRuntime 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.2-2'
testRuntime 'com.android.tools.build:gradle:2.3.2'
}

version = '0.8.1'

version = '0.9.0'
group = 'org.jmailen.gradle'
def pluginId = 'org.jmailen.kotlinter'

Expand Down
57 changes: 48 additions & 9 deletions src/main/kotlin/org/jmailen/gradle/kotlinter/KotlinterPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package org.jmailen.gradle.kotlinter

import com.android.build.gradle.AppExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.file.FileTree
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.internal.HasConvention
import org.gradle.api.plugins.JavaPluginConvention
Expand All @@ -12,12 +15,19 @@ import org.jmailen.gradle.kotlinter.tasks.LintTask

class KotlinterPlugin : Plugin<Project> {

val extendablePlugins = mapOf(
"org.jetbrains.kotlin.jvm" to this::kotlinSourceSets,
"kotlin-android" to this::androidSourceSets)

override fun apply(project: Project) {
val kotlinterExtention = project.extensions.create("kotlinter", KotlinterExtension::class.java)

// for known kotlin plugins, create tasks by convention.
project.plugins.withId("org.jetbrains.kotlin.jvm") {
KotlinterApplier(project).createTasks(project.kotlinSourceSets())
extendablePlugins.forEach { pluginId, sourceResolver ->
project.plugins.withId(pluginId) {
val sourceSets = sourceResolver(project)
KotlinterApplier(project).createTasks(sourceSets)
}
}

project.afterEvaluate {
Expand All @@ -27,7 +37,30 @@ class KotlinterPlugin : Plugin<Project> {
}
}

private fun Project.kotlinSourceSets() = sourceSets().map { it.kotlin }.filterNotNull()
private fun kotlinSourceSets(project: Project): List<SourceSetInfo> {
return project.sourceSets().map { it.kotlin }.filterNotNull().map {
SourceSetInfo(it.name, it.sourceDirectories)
}
}

private fun androidSourceSets(project: Project): List<SourceSetInfo> {
val android = project.extensions.findByName("android")
val sourceSetInfos = (android as? AppExtension)?.let {
it.sourceSets.map { androidSourceSet ->

val kotlinSourceTree = androidSourceSet.java.srcDirs.map { dir ->
project.fileTree(dir) {
it.include("**/*.kt")
}
}.reduce { merged: FileTree, tree ->
merged.plus(tree)
}

SourceSetInfo(androidSourceSet.name, kotlinSourceTree)
}
}
return sourceSetInfos ?: emptyList()
}

private fun Project.sourceSets() = convention.getPlugin(JavaPluginConvention::class.java).sourceSets

Expand All @@ -40,7 +73,8 @@ class KotlinterPlugin : Plugin<Project> {

class KotlinterApplier(val project: Project) {

fun createTasks(kotlinSourceSets: List<SourceDirectorySet>) {
fun createTasks(kotlinSourceSets: List<SourceSetInfo>) {

val formatTasks = kotlinSourceSets.map { createFormatTask(it) }

project.tasks.create("formatKotlin") {
Expand All @@ -62,19 +96,24 @@ class KotlinterApplier(val project: Project) {
}
}

fun createFormatTask(sourceSet: SourceDirectorySet) =
fun createFormatTask(sourceSet: SourceSetInfo) =
project.tasks.create("formatKotlin${sourceSet.id().capitalize()}", FormatTask::class.java) {
it.source(sourceSet.sourceDirectories.files)
it.source(sourceSet.files())
it.report = reportFile("${sourceSet.id()}-format.txt")
}

fun createLintTask(sourceSet: SourceDirectorySet) =
fun createLintTask(sourceSet: SourceSetInfo) =
project.tasks.create("lintKotlin${sourceSet.id().capitalize()}", LintTask::class.java) { task ->
task.source(sourceSet.sourceDirectories.files)
task.source(sourceSet.files())
task.report = reportFile("${sourceSet.id()}-lint.txt")
}

private fun reportFile(name: String) = project.file("${project.buildDir}/reports/ktlint/$name")
}

class SourceSetInfo(val name: String, val sourceDirectories: FileCollection) {

fun id() = name.split(" ").first()

private fun SourceDirectorySet.id() = name.split(" ").first()
fun files() = sourceDirectories.files
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.jmailen.gradle.kotlinter.support
import com.github.shyiko.ktlint.core.RuleSet
import com.github.shyiko.ktlint.core.RuleSetProvider
import java.util.ServiceLoader
import kotlin.comparisons.compareBy

fun resolveRuleSets(providers: Iterable<RuleSetProvider> = ServiceLoader.load(RuleSetProvider::class.java)): List<RuleSet> {
return providers.map { it.get() }.sortedWith(compareBy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import com.github.shyiko.ktlint.core.Rule
import com.github.shyiko.ktlint.core.RuleSet
import com.github.shyiko.ktlint.core.RuleSetProvider
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class RuleSetsTest {

Expand Down

0 comments on commit a0dbd2b

Please sign in to comment.