The project should work in IntelliJ IDEA 2018 and Android Studio 3.2/3.3. Current development is being done on IntelliJ IDEA 2019 EAP.
ANDROID_HOME
should be set to an Android SDK root folder.
This is required because the tests build full Android projects. For more info see Official Documentation on environment variables.- First make sure it runs successfully from terminal with
./gradlew tests
.- Check failure reasons (in JUnit report) for things to fix.
- This helps to rule out trivial problems during import.
- After it builds successfully, import the root
build.gradle.kts
into IDE.
Please report import problems if you encounter them, even if you fixed them, so I can add it here.
See test/README.md.
See test/README.md.
Every commit that's built on CI is deployed to Sonatype. The version is either in x.y-SNAPSHOT
or x.y.branch-SNAPSHOT
form.
The two main entry points are:
To use the -SNAPSHOT
builds it's necessary to declare the Sonatype repository:
// `repositories { }` in build.gradle > buildscript, or settings.gradle > pluginManagement, or buildSrc > build.gradle
maven {
name = "Sonatype 01: SNAPSHOTs"
url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
content {
includeGroup("net.twisterrob.gradle")
includeGroupByRegex("net\\.twisterrob\\.gradle\\.plugin\\..*")
}
mavenContent {
snapshotsOnly()
}
}
or
// `repositories { }` in build.gradle.kts > buildscript, or settings.gradle.kts > pluginManagement, or buildSrc > build.gradle.kts
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") {
name = "Sonatype 01: SNAPSHOTs"
content {
includeGroup("net.twisterrob.gradle")
includeGroupByRegex("""net\.twisterrob\.gradle\.plugin\..*""")
}
mavenContent {
snapshotsOnly()
}
}
and then business as usual, see README.md.
It's possible to deploy a snapshot into the current user's .m2
folder.
This is useful for testing on external local projects.
gradlew publishToMavenLocal
settings.gradle(.kts)
:
pluginManagement {
repositories {
mavenLocal() // make sure it's first
...
}
}
and then business as usual (e.g. plugins { ...
etc. see README.md).
This bypasses Gradle's dependency management and uses jars directly. The drawback is that each transitive dependency has to be manually added.
Add buildscript
block in root `build.gradle`
buildscript {
repositories {
mavenCentral()
def repoRoot = file($/P:\projects\workspace\net.twisterrob.gradle-quality/$).toURI()
ivy {
url = repoRoot
patternLayout {
artifact("[artifact]/build/libs/[artifact]-[revision](-[classifier]).[ext]")
}
}
ivy {
url = repoRoot
patternLayout {
artifact("checkers/[artifact]/build/libs/[artifact]-[revision](-[classifier]).[ext]")
}
}
}
dependencies {
configurations.classpath.resolutionStrategy.cacheChangingModulesFor(0, "seconds") // -SNAPSHOT
def VERSION_QUALITY = "0.2-SNAPSHOT"
classpath("net.twisterrob.gradle:twister-quality:${VERSION_QUALITY}")
classpath("net.twisterrob.gradle:twister-quality-common:${VERSION_QUALITY}")
classpath("net.twisterrob.gradle:twister-quality-checkstyle:${VERSION_QUALITY}")
classpath("net.twisterrob.gradle:twister-quality-pmd:${VERSION_QUALITY}")
classpath("se.bjurr.violations:violations-lib:1.50")
// ... maybe more transitive dependencies
}
}
To try it out, add printViolationCounts
from README.md and run gradlew checkstyleEach :printViolationCounts
.
The project is using a modular architecture to reduce coupling and so it's possible to use only part of the project.
Module (location): summary | Distributed Artifact, Gradle Plugin ID, JVM Package |
---|---|
quality (/quality ):All quality plugins bundled in one. |
classpath 'net.twisterrob.gradle:twister-quality:+' apply plugin: "net.twisterrob.gradle.plugin.quality" import net.twisterrob.gradle.quality; |
common (/common ):Shared classes between checkers. Not to be consumed directly. |
classpath "net.twisterrob.gradle:twister-quality-common:+" // apply plugin: N/A import net.twisterrob.gradle.common; |
checkstyle (/checkers/checkstyle ):Checkstyle setup plugin for Gradle. |
classpath "net.twisterrob.gradle:twister-quality-checkstyle:+" apply plugin: "net.twisterrob.gradle.plugin.checkstyle" import net.twisterrob.gradle.checkstyle; |
pmd (/checkers/pmd ):PMD setup plugin for Gradle. |
classpath "net.twisterrob.gradle:twister-quality-pmd:+" apply plugin: "net.twisterrob.gradle.plugin.pmd" import net.twisterrob.gradle.pmd; |
test (/test ):Gradle test plugin and resources. |
classpath "net.twisterrob.gradle:twister-gradle-test:+" apply plugin: "net.twisterrob.gradle.plugin.gradle.test" import net.twisterrob.gradle.test; |
plugin (/plugin ):Gradle Android plugin conventions. |
classpath "net.twisterrob.gradle:twister-convention-plugins:+" apply plugin: "net.twisterrob.gradle.plugin.android-app" apply plugin: "net.twisterrob.gradle.plugin.root" import net.twisterrob.gradle.android; |
Most of the code is written in Kotlin, some in Groovy to test the integration with traditional Gradle, and some in Java to test interop (mostly Generics).
Originally Groovy was the main language with
@CompileStatic
enabled so there's some type checking during compilation. Still after a successfulgroovyc
compilation it was possible to get unrunnable invalid class files, and the amount of time spent on finding workarounds and helping the static compiler to infer the types was more than the ease and fun of converting everything to Kotlin.