This repository has been archived by the owner on Feb 11, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #110 from tasomaniac/taso/ktlint-integration
Ktlint integration
- Loading branch information
Showing
13 changed files
with
234 additions
and
5 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
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
97 changes: 97 additions & 0 deletions
97
plugin/src/main/groovy/com/novoda/staticanalysis/internal/ktlint/KtlintConfigurator.groovy
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,97 @@ | ||
package com.novoda.staticanalysis.internal.ktlint | ||
|
||
import com.novoda.staticanalysis.StaticAnalysisExtension | ||
import com.novoda.staticanalysis.Violations | ||
import com.novoda.staticanalysis.internal.Configurator | ||
import com.novoda.staticanalysis.internal.VariantFilter | ||
import com.novoda.staticanalysis.internal.checkstyle.CollectCheckstyleViolationsTask | ||
import org.gradle.api.GradleException | ||
import org.gradle.api.NamedDomainObjectContainer | ||
import org.gradle.api.Project | ||
import org.gradle.api.Task | ||
|
||
class KtlintConfigurator implements Configurator { | ||
|
||
private static final String KTLINT_PLUGIN = 'org.jlleitschuh.gradle.ktlint' | ||
private static final String KTLINT_NOT_APPLIED = 'The Ktlint plugin is configured but not applied. Please apply the plugin in your build script.\nFor more information see https://github.com/jeremymailen/kotlinter-gradle' | ||
|
||
private final Project project | ||
private final Violations violations | ||
private final Task evaluateViolations | ||
private final VariantFilter variantFilter | ||
|
||
static KtlintConfigurator create(Project project, | ||
NamedDomainObjectContainer<Violations> violationsContainer, | ||
Task evaluateViolations) { | ||
Violations violations = violationsContainer.maybeCreate('ktlint') | ||
return new KtlintConfigurator(project, violations, evaluateViolations) | ||
} | ||
|
||
KtlintConfigurator(Project project, Violations violations, Task evaluateViolations) { | ||
this.project = project | ||
this.violations = violations | ||
this.evaluateViolations = evaluateViolations | ||
this.variantFilter = new VariantFilter(project) | ||
} | ||
|
||
@Override | ||
void execute() { | ||
project.extensions.findByType(StaticAnalysisExtension).ext.ktlint = { Closure config -> | ||
if (!project.plugins.hasPlugin(KTLINT_PLUGIN)) { | ||
throw new GradleException(KTLINT_NOT_APPLIED) | ||
} | ||
|
||
def ktlint = project.ktlint | ||
ktlint.ignoreFailures = true | ||
ktlint.reporters = ['CHECKSTYLE', 'PLAIN'] | ||
ktlint.ext.includeVariants = { Closure<Boolean> filter -> | ||
variantFilter.includeVariantsFilter = filter | ||
} | ||
config.delegate = ktlint | ||
config() | ||
|
||
project.afterEvaluate { | ||
|
||
project.plugins.withId("kotlin") { | ||
configureKotlinProject() | ||
} | ||
project.plugins.withId("kotlin2js") { | ||
configureKotlinProject() | ||
} | ||
project.plugins.withId("kotlin-platform-common") { | ||
configureKotlinProject() | ||
} | ||
project.plugins.withId('com.android.application') { | ||
configureAndroidWithVariants(variantFilter.filteredApplicationVariants) | ||
} | ||
project.plugins.withId('com.android.library') { | ||
configureAndroidWithVariants(variantFilter.filteredLibraryVariants) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private void configureKotlinProject() { | ||
project.sourceSets.each { configureKtlint(it) } | ||
} | ||
|
||
private void configureAndroidWithVariants(def mainVariants) { | ||
mainVariants.all { configureKtlint(it) } | ||
variantFilter.filteredTestVariants.all { configureKtlint(it) } | ||
variantFilter.filteredUnitTestVariants.all { configureKtlint(it) } | ||
} | ||
|
||
private void configureKtlint(def sourceSet) { | ||
def collectViolations = createCollectViolationsTask(violations, sourceSet.name) | ||
evaluateViolations.dependsOn collectViolations | ||
} | ||
|
||
private def createCollectViolationsTask(Violations violations, def sourceSetName) { | ||
project.tasks.create("collectKtlint${sourceSetName.capitalize()}Violations", CollectCheckstyleViolationsTask) { task -> | ||
task.xmlReportFile = new File(project.buildDir, "reports/ktlint/ktlint-${sourceSetName}.xml") | ||
task.htmlReportFile = new File(project.buildDir, "reports/ktlint/ktlint-${sourceSetName}.txt") | ||
task.violations = violations | ||
task.dependsOn project.tasks["ktlint${sourceSetName.capitalize()}Check"] | ||
} | ||
} | ||
} |
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 @@ | ||
data class ValidClass(val prop1: String, val prop2: Int) |
7 changes: 7 additions & 0 deletions
7
plugin/src/test/fixtures/sources/ktlint/with-error/KtLintViolator.kt
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,7 @@ | ||
class KtLintViolator { | ||
|
||
override fun equals(other: Any?): Boolean { | ||
// this is not allowed | ||
return true; | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
...in/src/test/groovy/com/novoda/staticanalysis/internal/ktlint/KtlintIntegrationTest.groovy
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,98 @@ | ||
package com.novoda.staticanalysis.internal.ktlint | ||
|
||
import com.novoda.test.Fixtures | ||
import com.novoda.test.TestProject | ||
import com.novoda.test.TestProjectRule | ||
import org.junit.Rule | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
import org.junit.runners.Parameterized | ||
|
||
import static com.novoda.test.LogsSubject.assertThat | ||
|
||
@RunWith(Parameterized.class) | ||
class KtlintIntegrationTest { | ||
|
||
private static final String KTLINT_NOT_APPLIED = 'The Ktlint plugin is configured but not applied. Please apply the plugin in your build script.' | ||
public static final String DEFAULT_CONFIG = ''' | ||
ktlint { | ||
includeVariants { it.name == "debug" } | ||
} | ||
''' | ||
public static final String EMPTY_CONFIG = 'ktlint {}' | ||
|
||
@Parameterized.Parameters(name = '{0}') | ||
static def rules() { | ||
return [ | ||
[TestProjectRule.forKotlinProject(), 'main'].toArray(), | ||
[TestProjectRule.forAndroidKotlinProject(), 'debug'].toArray() | ||
] | ||
} | ||
|
||
@Rule | ||
public final TestProjectRule projectRule | ||
private final String sourceSetName; | ||
|
||
KtlintIntegrationTest(TestProjectRule projectRule, String sourceSetName) { | ||
this.projectRule = projectRule | ||
this.sourceSetName = sourceSetName | ||
} | ||
|
||
@Test | ||
void shouldNotFailWhenKtlintIsNotConfigured() { | ||
def result = createProjectWith(Fixtures.Ktlint.SOURCES_WITH_ERROR) | ||
.build('evaluateViolations') | ||
|
||
assertThat(result.logs).doesNotContainKtlintViolations() | ||
} | ||
|
||
@Test | ||
void shouldFailBuildOnConfigurationWhenKtlintConfiguredButNotApplied() { | ||
def result = projectRule.newProject() | ||
.withToolsConfig(EMPTY_CONFIG) | ||
.buildAndFail('evaluateViolations') | ||
|
||
assertThat(result.logs).contains(KTLINT_NOT_APPLIED) | ||
} | ||
|
||
@Test | ||
void shouldFailBuildWhenKtlintErrorsOverTheThreshold() { | ||
def result = createProjectWith(Fixtures.Ktlint.SOURCES_WITH_ERROR) | ||
.withToolsConfig(DEFAULT_CONFIG) | ||
.buildAndFail('evaluateViolations') | ||
|
||
assertThat(result.logs).containsLimitExceeded(1, 0) | ||
assertThat(result.logs).containsKtlintViolations(1, | ||
result.buildFileUrl("reports/ktlint/ktlint-${sourceSetName}.txt")) | ||
} | ||
|
||
@Test | ||
void shouldNotFailWhenErrorsAreWithinThreshold() { | ||
def result = createProjectWith(Fixtures.Ktlint.SOURCES_WITH_ERROR, 1) | ||
.withToolsConfig(DEFAULT_CONFIG) | ||
.build('evaluateViolations') | ||
|
||
assertThat(result.logs).containsKtlintViolations(1, | ||
result.buildFileUrl("reports/ktlint/ktlint-${sourceSetName}.txt")) | ||
} | ||
|
||
@Test | ||
void shouldNotFailBuildWhenNoErrorsEncounteredAndNoThresholdTrespassed() { | ||
def result = createProjectWith(Fixtures.Ktlint.SOURCES_NO_ERROR, 0) | ||
.withToolsConfig(EMPTY_CONFIG) | ||
.build('evaluateViolations') | ||
|
||
assertThat(result.logs).doesNotContainLimitExceeded() | ||
assertThat(result.logs).doesNotContainKtlintViolations() | ||
} | ||
|
||
private TestProject createProjectWith(File sources, int maxErrors = 0) { | ||
projectRule.newProject() | ||
.withPlugin('org.jlleitschuh.gradle.ktlint', '4.1.0') | ||
.withSourceSet('main', sources) | ||
.withPenalty("""{ | ||
maxWarnings = 0 | ||
maxErrors = ${maxErrors} | ||
}""") | ||
} | ||
} |
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
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
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
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